Showing preview only (797K chars total). Download the full file or copy to clipboard to get everything.
Repository: saferwall/pe
Branch: main
Commit: 984afb23943d
Files: 91
Total size: 765.7 KB
Directory structure:
gitextract_so1rfj4w/
├── .editorconfig
├── .gitattributes
├── .github/
│ ├── FUNDING.YML
│ └── workflows/
│ └── ci.yaml
├── .gitignore
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── LICENSE
├── README.md
├── anomaly.go
├── anomaly_test.go
├── arch.go
├── boundimports.go
├── boundimports_test.go
├── cmd/
│ ├── dump.go
│ ├── main.go
│ ├── size.go
│ └── size_test.go
├── debug.go
├── debug_test.go
├── delayimports.go
├── delayimports_test.go
├── dosheader.go
├── dosheader_test.go
├── dotnet.go
├── dotnet_helper.go
├── dotnet_metadata_tables.go
├── dotnet_test.go
├── exception.go
├── exception_test.go
├── exports.go
├── exports_test.go
├── file.go
├── file_test.go
├── globalptr.go
├── go.mod
├── go.sum
├── helper.go
├── helper_test.go
├── iat.go
├── imports.go
├── imports_test.go
├── loadconfig.go
├── loadconfig_test.go
├── log/
│ ├── README.md
│ ├── filter.go
│ ├── filter_test.go
│ ├── global.go
│ ├── global_test.go
│ ├── helper.go
│ ├── helper_test.go
│ ├── level.go
│ ├── level_test.go
│ ├── log.go
│ ├── log_test.go
│ ├── std.go
│ ├── std_test.go
│ ├── value.go
│ └── value_test.go
├── ntheader.go
├── ntheader_test.go
├── ordlookup.go
├── overlay.go
├── overlay_test.go
├── pe.go
├── reloc.go
├── reloc_test.go
├── resource.go
├── resource_test.go
├── richheader.go
├── richheader_test.go
├── scripts/
│ ├── extract-rsrc-lang.py
│ └── ms-lcid.txt
├── section.go
├── section_test.go
├── security.go
├── security_linux_mac.go
├── security_test.go
├── security_windows.go
├── staticcheck.conf
├── symbol.go
├── symbol_test.go
├── test/
│ ├── WdBoot.sys
│ ├── acpi.sys
│ ├── amdi2c.sys
│ ├── amdxata.sys
│ └── look
├── tls.go
├── tls_test.go
├── version.go
└── version_test.go
================================================
FILE CONTENTS
================================================
================================================
FILE: .editorconfig
================================================
; https://editorconfig.org/
root = true
[*]
insert_final_newline = true
charset = utf-8
trim_trailing_whitespace = true
indent_style = space
indent_size = 2
[{Makefile,go.mod,go.sum,*.go,.gitmodules}]
indent_style = tab
indent_size = 4
[*.md]
indent_size = 4
trim_trailing_whitespace = false
eclint_indent_style = unset
[Dockerfile]
indent_size = 4
================================================
FILE: .gitattributes
================================================
# Treat all files in the Go repo as binary, with no git magic updating
# line endings. This produces predictable results in different environments.
#
# Windows users contributing to Go will need to use a modern version
# of git and editors capable of LF line endings.
#
# Windows .bat files are known to have multiple bugs when run with LF
# endings, and so they are checked in with CRLF endings, with a test
# in test/winbatch.go to catch problems. (See golang.org/issue/37791.)
#
# We'll prevent accidental CRLF line endings from entering the repo
# via the git-codereview gofmt checks and tests.
#
# See golang.org/issue/9281.
* -text
================================================
FILE: .github/FUNDING.YML
================================================
github: LordNoteworthy
================================================
FILE: .github/workflows/ci.yaml
================================================
name: Build & Test
on: [push]
jobs:
test:
name: Build & Test
strategy:
fail-fast: false
matrix:
go-version: [1.20.x, 1.21.x, 1.22.x, 1.23.x, 1.24.x, 1.25.x, 1.26.x]
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v6
- name: Install Go
uses: actions/setup-go@v6
with:
go-version: ${{ matrix.go-version }}
- name: Build
run: |
go env -w GOFLAGS=-mod=mod
go build -v ./...
- name: Extract test data
run: |
cd test
7z x "*.7z" -pinfected
- name: Test With Coverage
run: go test -race -coverprofile=coverage -covermode=atomic
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v2
with:
files: ./coverage
if: matrix.os == 'windows-latest' && matrix.go-version == '1.23.x'
- name: Go vet
run: |
go vet .
if: matrix.os == 'windows-latest' && matrix.go-version == '1.23.x'
- name: Staticcheck
uses: dominikh/staticcheck-action@v1.3.1
with:
version: "2024.1"
install-go: false
cache-key: ${{ matrix.go }}
if: matrix.os == 'windows-latest' && matrix.go-version == '1.23.x'
================================================
FILE: .gitignore
================================================
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
coverage
# Dependency directories (remove the comment below to include it)
vendor/
# Code editors configs
.idea/
.vscode/launch.json
# Go fuzz artefact
crashers/
suppressions/
# Log files
*.log
test/testdata/
================================================
FILE: CHANGELOG.md
================================================
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.4.0] - Unreleased
### Added
- Permit more granular control over which data directories are parsed by [rabbitstack](https://github.com/rabbitstack) [#72](https://github.com/saferwall/pe/pull/72).
- Support parsing the different `retpoline` types: Imported Address, Indirect Branch and Switchable retpoline [#70](https://github.com/saferwall/pe/pull/70).
- Unit tests for load config directory [#70](https://github.com/saferwall/pe/pull/69).
- Unit tests for TLS directory [#69](https://github.com/saferwall/pe/pull/69).
- Unit tests for debug directory [#68](https://github.com/saferwall/pe/pull/68).
- Unit tests for resource directory and add functions to prettify resource (sub)languages [#66](https://github.com/saferwall/pe/pull/66).
- Annotate PE structures with JSON tags during JSON encoding [#64](https://github.com/saferwall/pe/pull/64), [#65](https://github.com/saferwall/pe/pull/65) and [#67](https://github.com/saferwall/pe/pull/67).
- Improve PE dumper to print imports and unit test parsing imports data directory[#63](https://github.com/saferwall/pe/pull/63).
- Improve PE dumper to print section headers [#62](https://github.com/saferwall/pe/pull/62).
- Improve PE dumper to print PE headers [#61](https://github.com/saferwall/pe/pull/61).
- Add `SerialNumber`, `SignatureAlgorithm` and `PubKeyAlgorithm` to the `CertInfo` [#60](https://github.com/saferwall/pe/pull/60).
- Option to disable certificate validation [#59](https://github.com/saferwall/pe/pull/59).
- Improve PE dumper to print exceptions [#57](https://github.com/saferwall/pe/pull/57).
- Unit tests for debug directory [#49](https://github.com/saferwall/pe/pull/49).
### Fixed
- Bug while iterating over VolatileInfoRangeTable entries [#70](https://github.com/saferwall/pe/pull/70).
- Bug while iterating (additional padding and loop condition) over DVRT relocation block entries [#70](https://github.com/saferwall/pe/pull/70).
- Bug while appending (twice) Control Flow Guard IAT entries [#70](https://github.com/saferwall/pe/pull/70).
- Bug while parsing `POGO` debug entry types [#68](https://github.com/saferwall/pe/pull/68).
- `Authentihash()` for instances w/o fd thanks to [flanfly](https://github.com/flanfly) [#47](https://github.com/saferwall/pe/pull/47).
### Changed
- Some fields has been renamed for consistency:
- `RichHeader.XorKey` -> `RichHeader.XORKey`.
- Any `Rva` substring -> `RVA` and any `Iat` substring -> `IAT`.
- And many more.
- Some fields used internally in imports parsing were changed from a slice of pointers to a simple slice.
- Certificate.Content changed from `*pkcs7.PKCS7` to `pkcs7.PKCS7`.
- `Section.Entropy` changed from `float64` to `float64*` to distinguish between the case when the section entropy is equal to zero and the case when the entropy is equal to nil - meaning that it was never calculated.
- Remove `cobra` dependency from `cmd/pedumper` [#56](https://github.com/saferwall/pe/pull/56).
## [1.3.0] - 2022-08-04
## Added
- Authenticode signature validation in Windows [#43](https://github.com/saferwall/pe/pull/43).
- File information structure that helps to identify what parts of the PE file we have, such as `HasImports()` [#42](https://github.com/saferwall/pe/pull/42)..
- Calculate Rich header hash thanks to [wanglei-coder](https://github.com/wanglei-coder) [#38](https://github.com/saferwall/pe/pull/38).
- PE Overlay thanks to [wanglei-coder](https://github.com/wanglei-coder) [#37](https://github.com/saferwall/pe/pull/37).
- Unit tests for DOS header parsing.
- Unit tests for CLR directory [#34](https://github.com/saferwall/pe/pull/28).
- Unit tests for Rich header [#33](https://github.com/saferwall/pe/pull/33).
## Changed
- Do not return an error when parsing a data directory fails [#45](https://github.com/saferwall/pe/pull/45).
- Remove pointers from fields in the main `File` structure [#44](https://github.com/saferwall/pe/pull/44).
### Fixed
- Fix getting section data repeatedly thanks to [wanglei-coder](https://github.com/wanglei-coder) [#41](https://github.com/saferwall/pe/pull/41).
- Fix `adjustSectionAlignment()` thanks to [wanglei-coder](https://github.com/wanglei-coder) [#40](https://github.com/saferwall/pe/pull/40).
- Fix authentihash calculation thanks to [wanglei-coder](https://github.com/wanglei-coder) [#38](https://github.com/saferwall/pe/pull/38).
- Memory leak in `Close()` function that missed a call to `unmap()` thanks to [Mamba24L8](https://github.com/Mamba24L8).
## [1.2.0] - 2022-06-12
## Added
- Unit tests for export directory [#28](https://github.com/saferwall/pe/pull/28).
- Add a new option to allow usage of a custom logger [#24](https://github.com/saferwall/pe/pull/24).
- Unit tests for delay imports directory [#23](https://github.com/saferwall/pe/pull/23).
- Allow access to the raw certificates content [#22](https://github.com/saferwall/pe/pull/22).
- Unit tests for security directory [#19](https://github.com/saferwall/pe/pull/19).
- Unit tests for bound imports directory [#18](https://github.com/saferwall/pe/pull/18).
## Changed
- Make `GetData()` and `GetRVAFromOffset()` and `GetOffsetFromRva()` helper routines public.
- Keep parsing in exports directories even when anomalies are found [#26](https://github.com/saferwall/pe/pull/26).
## Fixed
- Incorrect check for `skipCertVerification` in security directory.
- Null pointer dereference in `GetExportFunctionByRVA()` and out of bounds when calculating `symbolAddress` in export directory [#28](https://github.com/saferwall/pe/pull/28).
- Reading unicode string from resource directory `readUnicodeStringAtRVA()` [#26](https://github.com/saferwall/pe/pull/26).
- Null pointer dereference in resource directory parsing [#25](https://github.com/saferwall/pe/pull/25).
- Imphash calculation [#17](https://github.com/saferwall/pe/pull/17) thanks to [@secDre4mer](https://github.com/secDre4mer).
- Null certificate header in security directory [#19](https://github.com/saferwall/pe/pull/19)
## [1.1.0] - 2021-12-20
### Added
- Add .editorconfig and .vscode config.
- Add github action CI workflow to test the package.
- Add few badges for the README.md to track build status, coverage and code quality.
- Introduce a new API to parse a file from a byte array.
- Parse .net metadata Module table.
- Parse .net metadata stream headers and metadata tables stream header.
- Add cmd/pedumper to illustrate how to use the library.
- Add unit test for relocation, exception, security, symbol, file, nt header, section and helper files.
- Add an option `New()` to customize max of relocations entries and COFF symbols to parse.
### Changed
- Remove uneeded break statements & lowercase error messages and anomalies.
- Make COFF entry in File struct a pointer.
- Remove unsafe pointer usage from resource directory.
- Do not return an error when COFF symbol table is not found.
- License from Apache 2 to MIT.
### Fixed
- Probe for invalid Nt Header offset.
- Fix authenticode hash calculation.
- Compile correctly on 32 bit thnkas to @Max Altgelt.
- COFF symbol table `readASCIIStringAtOffset()` out of bounds exception.
- Probe for optional header section alignment != 0.
- Fix infinite loop in exception unwind code parsing.
- Fix last data directory entry is reserved and must be zero.
- Safe ready of global pointer register
## [1.0.0] - 2021-03-04 (Initial Release)
- Works with PE32/PE32+ file fomat.
- Supports Intel x86/AMD64/ARM7ARM7 Thumb/ARM8-64/IA64/CHPE architectures.
- MS DOS header.
- Rich Header (calculate checksum).
- NT Header (file header + optional header).
- COFF symbol table and string table.
- Sections headers + entropy calculation.
- Data directories:
- Import Table + ImpHash calculation.
- Export Table.
- Resource Table.
- Exceptions Table.
- Security Table + Authentihash calculation.
- Relocations Table.
- Debug Table (CODEVIEW, POGO, VC FEATURE, REPRO, FPO, EXDLL CHARACTERISTICS debug types).
- TLS Table.
- Load Config Directory (SEH, GFID, GIAT, Guard LongJumps, CHPE, Dynamic Value Reloc Table, Enclave Configuration, Volatile Metadata tables).
- Bound Import Table.
- Delay Import Table.
- COM Table (CLR Metadata Header, Metadata Table Streams).
- Report several anomalies.
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at report@saferwall.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2021 Saferwall
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
<a href="https://saferwall.com" target="_blank" rel="noopener noreferrer"><img align="right" width="300" src=".github/assets/logo.png" alt="Saferwall logo"></a>
# Portable Executable Parser
[](https://pkg.go.dev/github.com/saferwall/pe)  [](https://goreportcard.com/report/github.com/saferwall/pe) [](https://codecov.io/gh/saferwall/pe) 
**pe** is a go package for parsing the [portable executable](https://docs.microsoft.com/en-us/windows/win32/debug/pe-format) file format. This package was designed with malware analysis in mind, and being resistent to PE malformations.
## Table of content
- [Portable Executable Parser](#portable-executable-parser)
- [Table of content](#table-of-content)
- [Features](#features)
- [Installing](#installing)
- [Using the library](#using-the-library)
- [PE Header](#pe-header)
- [Rich Header](#rich-header)
- [Iterating over sections](#iterating-over-sections)
- [Roadmap](#roadmap)
- [Fuzz Testing](#fuzz-testing)
- [Projects Using This Library](#projects-using-this-library)
- [References](#references)
## Features
- Works with PE32/PE32+ file format.
- Supports Intel x86/AMD64/ARM7ARM7 Thumb/ARM8-64/IA64/CHPE architectures.
- MS DOS header.
- Rich Header (calculate checksum and hash).
- NT Header (file header + optional header).
- COFF symbol table and string table.
- Sections headers + entropy calculation.
- Data directories
- Import Table + ImpHash calculation.
- Export Table
- Resource Table
- Exceptions Table
- Security Table + Authentihash calculation.
- Relocations Table
- Debug Table (CODEVIEW, POGO, VC FEATURE, REPRO, FPO, EXDLL CHARACTERISTICS debug types).
- TLS Table
- Load Config Directory (SEH, GFID, GIAT, Guard LongJumps, CHPE, Dynamic Value Reloc Table, Enclave Configuration, Volatile Metadata tables).
- Bound Import Table
- Delay Import Table
- COM Table (CLR Metadata Header, Metadata Table Streams)
- Report several anomalies
## Installing
Using this go package is easy. First, use `go get` to install the latest version of the library. This command will install the `pedumper` executable along with the library and its dependencies:
go get -u github.com/saferwall/pe
Next, include `pe` package in your application:
```go
import "github.com/saferwall/pe"
```
## Using the library
```go
package main
import (
peparser "github.com/saferwall/pe"
)
func main() {
filename := "C:\\Binaries\\notepad.exe"
pe, err := peparser.New(filename, &peparser.Options{})
if err != nil {
log.Fatalf("Error while opening file: %s, reason: %v", filename, err)
}
err = pe.Parse()
if err != nil {
log.Fatalf("Error while parsing file: %s, reason: %v", filename, err)
}
}
```
Start by instantiating a pe object by called the `New()` method, which takes the file path to the file to be parsed and some optional options.
Afterwards, a call to the `Parse()` method will give you access to all the different part of the PE format, directly accessible to be used. Here is the definition of the struct:
```go
type File struct {
DOSHeader ImageDOSHeader `json:"dos_header,omitempty"`
RichHeader RichHeader `json:"rich_header,omitempty"`
NtHeader ImageNtHeader `json:"nt_header,omitempty"`
COFF COFF `json:"coff,omitempty"`
Sections []Section `json:"sections,omitempty"`
Imports []Import `json:"imports,omitempty"`
Export Export `json:"export,omitempty"`
Debugs []DebugEntry `json:"debugs,omitempty"`
Relocations []Relocation `json:"relocations,omitempty"`
Resources ResourceDirectory `json:"resources,omitempty"`
TLS TLSDirectory `json:"tls,omitempty"`
LoadConfig LoadConfig `json:"load_config,omitempty"`
Exceptions []Exception `json:"exceptions,omitempty"`
Certificates CertificateSection `json:"certificates,omitempty"`
DelayImports []DelayImport `json:"delay_imports,omitempty"`
BoundImports []BoundImportDescriptorData `json:"bound_imports,omitempty"`
GlobalPtr uint32 `json:"global_ptr,omitempty"`
CLR CLRData `json:"clr,omitempty"`
IAT []IATEntry `json:"iat,omitempty"`
Anomalies []string `json:"anomalies,omitempty"`
Header []byte
data mmap.MMap
FileInfo
size uint32
OverlayOffset int64
f *os.File
opts *Options
logger *log.Helper
}
```
### PE Header
As mentioned before, all members of the struct are directly (no getters) accessible, additionally, the fields types has been preserved as the spec defines them, that means if you need to show the prettified version of an `int` type, you have to call the corresponding helper function.
```go
fmt.Printf("Magic is: 0x%x\n", pe.DOSHeader.Magic)
fmt.Printf("Signature is: 0x%x\n", pe.NtHeader.Signature)
fmt.Printf("Machine is: 0x%x, Meaning: %s\n", pe.NtHeader.FileHeader.Machine, pe.NtHeader.FileHeader.Machine.String())
```
Output:
```
Magic is: 0x5a4d
Signature is: 0x4550
Machine is: 0x8664, Meaning: x64
```
### Rich Header
Example:
```go
richHeader, _ := json.Marshal(pe.RichHeader)
fmt.Print(prettyPrint(richHeader))
```
Output:
```json
{
"XorKey": 2796214951,
"CompIDs": [
{
"MinorCV": 27412,
"ProdID": 257,
"Count": 4,
"Unmasked": 16870164
},
{
"MinorCV": 30729,
"ProdID": 147,
"Count": 193,
"Unmasked": 9664521
},
{
"MinorCV": 0,
"ProdID": 1,
"Count": 1325,
"Unmasked": 65536
},
{
"MinorCV": 27412,
"ProdID": 260,
"Count": 9,
"Unmasked": 17066772
},
{
"MinorCV": 27412,
"ProdID": 259,
"Count": 3,
"Unmasked": 17001236
},
{
"MinorCV": 27412,
"ProdID": 256,
"Count": 1,
"Unmasked": 16804628
},
{
"MinorCV": 27412,
"ProdID": 269,
"Count": 209,
"Unmasked": 17656596
},
{
"MinorCV": 27412,
"ProdID": 255,
"Count": 1,
"Unmasked": 16739092
},
{
"MinorCV": 27412,
"ProdID": 258,
"Count": 1,
"Unmasked": 16935700
}
],
"DansOffset": 128,
"Raw": "47vE9afaqqan2qqmp9qqprOxq6ej2qqmrqI5pmbaqqan2qumit+qprOxrqeu2qqms7Gpp6TaqqazsaqnptqqprOxp6d22qqms7FVpqbaqqazsainptqqplJpY2in2qqm"
}
```
### Iterating over sections
```go
for _, sec := range pe.Sections {
fmt.Printf("Section Name : %s\n", sec.NameString())
fmt.Printf("Section VirtualSize : %x\n", sec.Header.VirtualSize)
fmt.Printf("Section Flags : %x, Meaning: %v\n\n",
sec.Header.Characteristics, sec.PrettySectionFlags())
}
```
Output:
```
Section Name : .text
Section VirtualSize : 2ea58
Section Flags : 60500060, Meaning: [Align8Bytes Readable Align16Bytes Executable Contains Code Initialized Data Align1Bytes]
Section Name : .data
Section VirtualSize : 58
Section Flags : c0500040, Meaning: [Readable Initialized Data Writable Align1Bytes Align16Bytes Align8Bytes]
Section Name : .rdata
Section VirtualSize : 18d0
Section Flags : 40600040, Meaning: [Align2Bytes Align8Bytes Readable Initialized Data Align32Bytes]
...
```
## Roadmap
- imports MS-styled names demangling
- PE: VB5 and VB6 typical structures: project info, DLLCall-imports, referenced modules, object table
## Fuzz Testing
To validate the parser we use the [go-fuzz](https://github.com/dvyukov/go-fuzz) and a corpus of known malformed and tricky PE files from [corkami](https://github.com/corkami/pocs/tree/master/PE).
## Projects Using This Library
<a href="https://www.fibratus.io" >
<img src="https://github.com/rabbitstack/fibratus/raw/master/logo.png" alt="Fibratus" width="50px">
</a>
[Fibratus](https://github.com/rabbitstack/fibratus) A modern tool for Windows kernel exploration and tracing with a focus on security.
## References
- [Peering Inside the PE: A Tour of the Win32 Portable Executable File Format by Matt Pietrek](http://bytepointer.com/resources/pietrek_peering_inside_pe.htm)
- [An In-Depth Look into the Win32 Portable Executable File Format - Part 1 by Matt Pietrek](http://www.delphibasics.info/home/delphibasicsarticles/anin-depthlookintothewin32portableexecutablefileformat-part1)
- [An In-Depth Look into the Win32 Portable Executable File Format - Part 2 by Matt Pietrek](http://www.delphibasics.info/home/delphibasicsarticles/anin-depthlookintothewin32portableexecutablefileformat-part2)
- [Portable Executable File Format](https://blog.kowalczyk.info/articles/pefileformat.html)
- [PE Format MSDN spec](https://docs.microsoft.com/en-us/windows/win32/debug/pe-format)
- [DotNET format](https://www.ntcore.com/files/dotnetformat.htm)
- [BlackHat 2011 - CONSTANT INSECURITY: (PECOFF) Portable Executable FIle Format](https://www.youtube.com/watch?v=uoQL3CE24ls)
================================================
FILE: anomaly.go
================================================
// Copyright 2021 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.
package pe
import (
"encoding/binary"
"time"
)
// Anomalies found in a PE
var (
// AnoPEHeaderOverlapDOSHeader is reported when the PE headers overlaps with the DOS header.
AnoPEHeaderOverlapDOSHeader = "PE header overlaps with DOS header"
// AnoPETimeStampNull is reported when the file header timestamp is 0.
AnoPETimeStampNull = "file header timestamp set to 0"
// AnoPETimeStampFuture is reported when the file header timestamp is more
// than one day ahead of the current date timestamp.
AnoPETimeStampFuture = "file header timestamp set to 0"
// NumberOfSections is reported when number of sections is larger or equal than 10.
AnoNumberOfSections10Plus = "number of sections is 10+"
// AnoNumberOfSectionsNull is reported when sections count's is 0.
AnoNumberOfSectionsNull = "number of sections is 0"
// AnoSizeOfOptionalHeaderNull is reported when size of optional header is 0.
AnoSizeOfOptionalHeaderNull = "size of optional header is 0"
// AnoUncommonSizeOfOptionalHeader32 is reported when size of optional
// header for PE32 is larger than 0xE0.
AnoUncommonSizeOfOptionalHeader32 = "size of optional header is larger than 0xE0 (PE32)"
// AnoUncommonSizeOfOptionalHeader64 is reported when size of optional
// header for PE32+ is larger than 0xF0.
AnoUncommonSizeOfOptionalHeader64 = "size of optional header is larger than 0xF0 (PE32+)"
// AnoAddressOfEntryPointNull is reported when address of entry point is 0.
AnoAddressOfEntryPointNull = "address of entry point is 0"
// AnoAddressOfEPLessSizeOfHeaders is reported when address of entry point
// is smaller than size of headers, the file cannot run under Windows.
AnoAddressOfEPLessSizeOfHeaders = "address of entry point is smaller than size of headers, " +
"the file cannot run under Windows 8"
// AnoImageBaseNull is reported when the image base is null.
AnoImageBaseNull = "image base is 0"
// AnoDanSMagicOffset is reported when the `DanS` magic offset is different than 0x80.
AnoDanSMagicOffset = "`DanS` magic offset is different than 0x80"
// ErrInvalidFileAlignment is reported when file alignment is larger than
// 0x200 and not a power of 2.
ErrInvalidFileAlignment = "FileAlignment larger than 0x200 and not a power of 2"
// ErrInvalidSectionAlignment is reported when file alignment is lesser
// than 0x200 and different from section alignment.
ErrInvalidSectionAlignment = "FileAlignment lesser than 0x200 and different from section alignment"
// AnoMajorSubsystemVersion is reported when MajorSubsystemVersion has a
// value different than the standard 3 --> 6.
AnoMajorSubsystemVersion = "MajorSubsystemVersion is outside 3<-->6 boundary"
// AnonWin32VersionValue is reported when Win32VersionValue is different than 0
AnonWin32VersionValue = "Win32VersionValue is a reserved field, must be set to zero"
// AnoInvalidPEChecksum is reported when the optional header checksum field
// is different from what it should normally be.
AnoInvalidPEChecksum = "optional header checksum is invalid"
// AnoNumberOfRvaAndSizes is reported when NumberOfRvaAndSizes is different than 16.
AnoNumberOfRvaAndSizes = "optional header NumberOfRvaAndSizes != 16"
// AnoReservedDataDirectoryEntry is reported when the last data directory entry is not zero.
AnoReservedDataDirectoryEntry = "last data directory entry is a reserved field, must be set to zero"
// AnoCOFFSymbolsCount is reported when the number of COFF symbols is absurdly high.
AnoCOFFSymbolsCount = "COFF symbols count is absurdly high"
// AnoRelocationEntriesCount is reported when the number of relocation entries is absurdly high.
AnoRelocationEntriesCount = "relocation entries count is absurdly high"
)
// GetAnomalies reportes anomalies found in a PE binary.
// These nomalies does prevent the Windows loader from loading the files but
// is an interesting features for malware analysis.
func (pe *File) GetAnomalies() error {
// ******************** Anomalies in File header ************************
// An application for Windows NT typically has the nine predefined sections
// named: .text, .bss, .rdata, .data, .rsrc, .edata, .idata, .pdata, and
// .debug. Some applications do not need all of these sections, while
// others may define still more sections to suit their specific needs.
// NumberOfSections can be up to 96 under XP.
// NumberOfSections can be up to 65535 under Vista and later.
if pe.NtHeader.FileHeader.NumberOfSections >= 10 {
pe.Anomalies = append(pe.Anomalies, AnoNumberOfSections10Plus)
}
// File header timestamp set to 0.
if pe.NtHeader.FileHeader.TimeDateStamp == 0 {
pe.Anomalies = append(pe.Anomalies, AnoPETimeStampNull)
}
// File header timestamp set to the future.
now := time.Now()
future := uint32(now.Add(24 * time.Hour).Unix())
if pe.NtHeader.FileHeader.TimeDateStamp > future {
pe.Anomalies = append(pe.Anomalies, AnoPETimeStampFuture)
}
// NumberOfSections can be null with low alignment PEs
// and in this case, the values are just checked but not really used (under XP)
if pe.NtHeader.FileHeader.NumberOfSections == 0 {
pe.Anomalies = append(pe.Anomalies, AnoNumberOfSectionsNull)
}
// SizeOfOptionalHeader is not the size of the optional header, but the delta
// between the top of the Optional header and the start of the section table.
// Thus, it can be null (the section table will overlap the Optional Header,
// or can be null when no sections are present)
if pe.NtHeader.FileHeader.SizeOfOptionalHeader == 0 {
pe.Anomalies = append(pe.Anomalies, AnoSizeOfOptionalHeaderNull)
}
// SizeOfOptionalHeader can be bigger than the file
// (the section table will be in virtual space, full of zeroes), but can't be negative.
// Do some check here.
oh32 := ImageOptionalHeader32{}
oh64 := ImageOptionalHeader64{}
// SizeOfOptionalHeader standard value is 0xE0 for PE32.
if pe.Is32 &&
pe.NtHeader.FileHeader.SizeOfOptionalHeader > uint16(binary.Size(oh32)) {
pe.Anomalies = append(pe.Anomalies, AnoUncommonSizeOfOptionalHeader32)
}
// SizeOfOptionalHeader standard value is 0xF0 for PE32+.
if pe.Is64 &&
pe.NtHeader.FileHeader.SizeOfOptionalHeader > uint16(binary.Size(oh64)) {
pe.Anomalies = append(pe.Anomalies, AnoUncommonSizeOfOptionalHeader64)
}
// ***************** Anomalies in Optional header *********************
// Under Windows 8, AddressOfEntryPoint is not allowed to be smaller than
// SizeOfHeaders, except if it's null.
switch pe.Is64 {
case true:
oh64 = pe.NtHeader.OptionalHeader.(ImageOptionalHeader64)
case false:
oh32 = pe.NtHeader.OptionalHeader.(ImageOptionalHeader32)
}
// Use oh for fields which are common for both structures.
oh := oh32
if oh.AddressOfEntryPoint != 0 && oh.AddressOfEntryPoint < oh.SizeOfHeaders {
pe.Anomalies = append(pe.Anomalies, AnoAddressOfEPLessSizeOfHeaders)
}
// AddressOfEntryPoint can be null in DLLs: in this case,
// DllMain is just not called. can be null
if oh.AddressOfEntryPoint == 0 {
pe.Anomalies = append(pe.Anomalies, AnoAddressOfEntryPointNull)
}
// ImageBase can be null, under XP.
// In this case, the binary will be relocated to 10000h
if (pe.Is64 && oh64.ImageBase == 0) ||
(pe.Is32 && oh32.ImageBase == 0) {
pe.Anomalies = append(pe.Anomalies, AnoImageBaseNull)
}
// The msdn states that SizeOfImage must be a multiple of the section
// alignment. This is not a requirement though. Adding it as anomaly.
// Todo: raise an anomaly when SectionAlignment is NULL ?
if oh.SectionAlignment != 0 && oh.SizeOfImage%oh.SectionAlignment != 0 {
pe.Anomalies = append(pe.Anomalies, AnoInvalidSizeOfImage)
}
// For DLLs, MajorSubsystemVersion is ignored until Windows 8. It can have
// any value. Under Windows 8, it needs a standard value (3.10 < 6.30).
if oh.MajorSubsystemVersion < 3 || oh.MajorSubsystemVersion > 6 {
pe.Anomalies = append(pe.Anomalies, AnoMajorSubsystemVersion)
}
// Win32VersionValue officially defined as `reserved` and should be null
// if non null, it overrides MajorVersion/MinorVersion/BuildNumber/PlatformId
// OperatingSystem Versions values located in the PEB, after loading.
if oh.Win32VersionValue != 0 {
pe.Anomalies = append(pe.Anomalies, AnonWin32VersionValue)
}
// Checksums are required for kernel-mode drivers and some system DLLs.
// Otherwise, this field can be 0.
if pe.Checksum() != oh.CheckSum && oh.CheckSum != 0 {
pe.Anomalies = append(pe.Anomalies, AnoInvalidPEChecksum)
}
// This field contains the number of IMAGE_DATA_DIRECTORY entries.
// This field has been 16 since the earliest releases of Windows NT.
if (pe.Is64 && oh64.NumberOfRvaAndSizes == 0xA) ||
(pe.Is32 && oh32.NumberOfRvaAndSizes == 0xA) {
pe.Anomalies = append(pe.Anomalies, AnoNumberOfRvaAndSizes)
}
return nil
}
// addAnomaly appends the given anomaly to the list of anomalies.
func (pe *File) addAnomaly(anomaly string) {
if !stringInSlice(anomaly, pe.Anomalies) {
pe.Anomalies = append(pe.Anomalies, anomaly)
}
}
================================================
FILE: anomaly_test.go
================================================
// Copyright 2021 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.
package pe
import (
"testing"
)
func TestGetAnomalies(t *testing.T) {
tests := []struct {
in string
out []string
}{
{
getAbsoluteFilePath(
"test/050708404553416d103652a7ca1f887ab81f533a019a0eeff0e6bb460a202cde"),
[]string{AnoReservedDataDirectoryEntry},
},
{
getAbsoluteFilePath(
"test/0585495341e0ffaae1734acb78708ff55cd3612d844672d37226ef63d12652d0"),
[]string{AnoAddressOfEntryPointNull, AnoMajorSubsystemVersion},
},
}
for _, tt := range tests {
t.Run(tt.in, func(t *testing.T) {
file, err := New(tt.in, &Options{})
if err != nil {
t.Fatalf("New(%s) failed, reason: %v", tt.in, err)
}
err = file.Parse()
if err != nil {
t.Fatalf("Parse(%s) failed, reason: %v", tt.in, err)
}
err = file.GetAnomalies()
if err != nil {
t.Fatalf("GetAnomalies(%s) failed, reason: %v", tt.in, err)
}
for _, ano := range tt.out {
if !stringInSlice(ano, file.Anomalies) {
t.Errorf("anomaly(%s) not found in anomalies, got: %v", ano, file.Anomalies)
}
}
})
}
}
================================================
FILE: arch.go
================================================
// Copyright 2022 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.
package pe
// Architecture-specific data. This data directory is not used
// (set to all zeros) for I386, IA64, or AMD64 architecture.
func (pe *File) parseArchitectureDirectory(rva, size uint32) error {
return nil
}
================================================
FILE: boundimports.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.
package pe
import (
"encoding/binary"
)
const (
// MaxStringLength represents the maximum length of a string to be retrieved
// from the file. It's there to prevent loading massive amounts of data from
// memory mapped files. Strings longer than 0x100B should be rather rare.
MaxStringLength = uint32(0x100)
)
// ImageBoundImportDescriptor represents the IMAGE_BOUND_IMPORT_DESCRIPTOR.
type ImageBoundImportDescriptor struct {
// TimeDateStamp is just the value from the Exports information of the DLL
// which is being imported from.
TimeDateStamp uint32 `json:"time_date_stamp"`
// Offset of the DLL name counted from the beginning of the BOUND_IMPORT table.
OffsetModuleName uint16 `json:"offset_module_name"`
// Number of forwards,
NumberOfModuleForwarderRefs uint16 `json:"number_of_module_forwarder_refs"`
// Array of zero or more IMAGE_BOUND_FORWARDER_REF follows.
}
// ImageBoundForwardedRef represents the IMAGE_BOUND_FORWARDER_REF.
type ImageBoundForwardedRef struct {
TimeDateStamp uint32 `json:"time_date_stamp"`
OffsetModuleName uint16 `json:"offset_module_name"`
Reserved uint16 `json:"reserved"`
}
// BoundImportDescriptorData represents the descriptor in addition to forwarded refs.
type BoundImportDescriptorData struct {
Struct ImageBoundImportDescriptor `json:"struct"`
Name string `json:"name"`
ForwardedRefs []BoundForwardedRefData `json:"forwarded_refs"`
}
// BoundForwardedRefData represents the struct in addition to the dll name.
type BoundForwardedRefData struct {
Struct ImageBoundForwardedRef `json:"struct"`
Name string `json:"name"`
}
// This table is an array of bound import descriptors, each of which describes
// a DLL this image was bound up with at the time of the image creation.
// The descriptors also carry the time stamps of the bindings, and if the
// bindings are up-to-date, the OS loader uses these bindings as a “shortcut”
// for API import. Otherwise, the loader ignores the bindings and resolves the
// imported APIs through the Import tables.
func (pe *File) parseBoundImportDirectory(rva, size uint32) (err error) {
var sectionsAfterOffset []uint32
var safetyBoundary uint32
var start = rva
for {
bndDesc := ImageBoundImportDescriptor{}
bndDescSize := uint32(binary.Size(bndDesc))
err = pe.structUnpack(&bndDesc, rva, bndDescSize)
// If the RVA is invalid all would blow up. Some EXEs seem to be
// specially nasty and have an invalid RVA.
if err != nil {
return err
}
// If the structure is all zeros, we reached the end of the list.
if bndDesc == (ImageBoundImportDescriptor{}) {
break
}
rva += bndDescSize
sectionsAfterOffset = nil
fileOffset := pe.GetOffsetFromRva(rva)
section := pe.getSectionByRva(rva)
if section == nil {
safetyBoundary = pe.size - fileOffset
for _, section := range pe.Sections {
if section.Header.PointerToRawData > fileOffset {
sectionsAfterOffset = append(
sectionsAfterOffset, section.Header.PointerToRawData)
}
}
if len(sectionsAfterOffset) > 0 {
// Find the first section starting at a later offset than that
// specified by 'rva'
firstSectionAfterOffset := Min(sectionsAfterOffset)
section = pe.getSectionByOffset(firstSectionAfterOffset)
if section != nil {
safetyBoundary = section.Header.PointerToRawData - fileOffset
}
}
} else {
sectionLen := uint32(len(section.Data(0, 0, pe)))
safetyBoundary = (section.Header.PointerToRawData + sectionLen) - fileOffset
}
if section == nil {
pe.logger.Warnf("RVA of IMAGE_BOUND_IMPORT_DESCRIPTOR points to an invalid address: 0x%x", rva)
return nil
}
bndFrwdRef := ImageBoundForwardedRef{}
bndFrwdRefSize := uint32(binary.Size(bndFrwdRef))
count := min(uint32(bndDesc.NumberOfModuleForwarderRefs), safetyBoundary/bndFrwdRefSize)
forwarderRefs := make([]BoundForwardedRefData, 0)
for i := uint32(0); i < count; i++ {
err = pe.structUnpack(&bndFrwdRef, rva, bndFrwdRefSize)
if err != nil {
return err
}
rva += bndFrwdRefSize
offset := start + uint32(bndFrwdRef.OffsetModuleName)
DllNameBuff := string(pe.GetStringFromData(0, pe.data[offset:offset+MaxStringLength]))
DllName := string(DllNameBuff)
// OffsetModuleName points to a DLL name. These shouldn't be too long.
// Anything longer than a safety length of 128 will be taken to indicate
// a corrupt entry and abort the processing of these entries.
// Names shorter than 4 characters will be taken as invalid as well.
if DllName != "" && (len(DllName) > 256 || !IsPrintable(DllName)) {
break
}
forwarderRefs = append(forwarderRefs, BoundForwardedRefData{
Struct: bndFrwdRef, Name: DllName})
}
offset := start + uint32(bndDesc.OffsetModuleName)
DllNameBuff := pe.GetStringFromData(0, pe.data[offset:offset+MaxStringLength])
DllName := string(DllNameBuff)
if DllName != "" && (len(DllName) > 256 || !IsPrintable(DllName)) {
break
}
pe.BoundImports = append(pe.BoundImports, BoundImportDescriptorData{
Struct: bndDesc,
Name: DllName,
ForwardedRefs: forwarderRefs})
}
if len(pe.BoundImports) > 0 {
pe.HasBoundImp = true
}
return nil
}
================================================
FILE: boundimports_test.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.
package pe
import (
"reflect"
"testing"
)
type TestBoundImportEntry struct {
entryCount int
entryIndex int
entry BoundImportDescriptorData
errOutOfBounds error
}
func TestBoundImportDirectory(t *testing.T) {
tests := []struct {
in string
out TestBoundImportEntry
}{
{
getAbsoluteFilePath("test/mfc40u.dll"),
TestBoundImportEntry{
entryCount: 4,
entryIndex: 0,
entry: BoundImportDescriptorData{
Struct: ImageBoundImportDescriptor{
TimeDateStamp: 0x31CB50F3,
OffsetModuleName: 0x38,
NumberOfModuleForwarderRefs: 0x1,
},
Name: "MSVCRT40.dll",
ForwardedRefs: []BoundForwardedRefData{
{
Struct: ImageBoundForwardedRef{
TimeDateStamp: 0x3B7DFE0E,
OffsetModuleName: 0x45,
Reserved: 0x0,
},
Name: "msvcrt.DLL",
},
},
},
errOutOfBounds: nil,
},
},
{
// fake bound imports directory
getAbsoluteFilePath("test/0044e1870806c048a7558082d4482d1650dcd3ea73152ed2218a554983130721"),
TestBoundImportEntry{
errOutOfBounds: ErrOutsideBoundary,
},
},
}
for _, tt := range tests {
t.Run(tt.in, func(t *testing.T) {
ops := Options{Fast: true}
file, err := New(tt.in, &ops)
if err != nil {
t.Fatalf("New(%s) failed, reason: %v", tt.in, err)
}
err = file.Parse()
if err != nil {
t.Fatalf("Parse(%s) failed, reason: %v", tt.in, err)
}
var va, size uint32
if file.Is64 {
oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
dirEntry := oh64.DataDirectory[ImageDirectoryEntryBoundImport]
va = dirEntry.VirtualAddress
size = dirEntry.Size
} else {
oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
dirEntry := oh32.DataDirectory[ImageDirectoryEntryBoundImport]
va = dirEntry.VirtualAddress
size = dirEntry.Size
}
err = file.parseBoundImportDirectory(va, size)
if err != tt.out.errOutOfBounds {
t.Fatalf("parseBoundImportDirectory(%s) failed, reason: %v", tt.in, err)
}
got := file.BoundImports
if len(got) != tt.out.entryCount {
t.Errorf("bound imports entry count assertion failed, got %v, want %v", len(got), tt.out.entryCount)
}
if len(file.BoundImports) > 0 {
boundImportEntry := file.BoundImports[tt.out.entryIndex]
if !reflect.DeepEqual(boundImportEntry, tt.out.entry) {
t.Errorf("bound import entry assertion failed, got %v, want %v", boundImportEntry, tt.out.entry)
}
}
})
}
}
================================================
FILE: cmd/dump.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.
package main
import (
"bytes"
"encoding/binary"
"encoding/hex"
"encoding/json"
"fmt"
"os"
"path/filepath"
"reflect"
"strings"
"sync"
"text/tabwriter"
"time"
"unicode"
"unsafe"
peparser "github.com/saferwall/pe"
"github.com/saferwall/pe/log"
)
var (
wg sync.WaitGroup
jobs chan string = make(chan string)
)
func loopFilesWorker(cfg config) error {
for path := range jobs {
files, err := os.ReadDir(path)
if err != nil {
wg.Done()
return err
}
for _, file := range files {
if !file.IsDir() {
fullpath := filepath.Join(path, file.Name())
parsePE(fullpath, cfg)
}
}
wg.Done()
}
return nil
}
func LoopDirsFiles(path string) error {
files, err := os.ReadDir(path)
if err != nil {
return err
}
go func() {
wg.Add(1)
jobs <- path
}()
for _, file := range files {
if file.IsDir() {
LoopDirsFiles(filepath.Join(path, file.Name()))
}
}
return nil
}
func prettyPrint(iface interface{}) string {
var prettyJSON bytes.Buffer
buff, _ := json.Marshal(iface)
err := json.Indent(&prettyJSON, buff, "", "\t")
if err != nil {
log.Errorf("JSON parse error: %v", err)
return string(buff)
}
return prettyJSON.String()
}
func humanizeTimestamp(ts uint32) string {
unixTimeUTC := time.Unix(int64(ts), 0)
return unixTimeUTC.String()
}
func hexDump(b []byte) {
var a [16]byte
n := (len(b) + 15) &^ 15
for i := 0; i < n; i++ {
if i%16 == 0 {
fmt.Printf("%4d", i)
}
if i%8 == 0 {
fmt.Print(" ")
}
if i < len(b) {
fmt.Printf(" %02X", b[i])
} else {
fmt.Print(" ")
}
if i >= len(b) {
a[i%16] = ' '
} else if b[i] < 32 || b[i] > 126 {
a[i%16] = '.'
} else {
a[i%16] = b[i]
}
if i%16 == 15 {
fmt.Printf(" %s\n", string(a[:]))
}
}
}
func hexDumpSize(b []byte, size int) {
var a [16]byte
// Append null bytes when length of the buffer
// is smaller than the requested size.
if len(b) < size {
temp := make([]byte, size)
copy(temp, b)
b = temp
}
n := (size + 15) &^ 15
for i := 0; i < n; i++ {
if i%16 == 0 {
fmt.Printf("%4d", i)
}
if i%8 == 0 {
fmt.Print(" ")
}
if i < len(b) {
fmt.Printf(" %02X", b[i])
} else {
fmt.Print(" ")
}
if i >= len(b) {
a[i%16] = ' '
} else if b[i] < 32 || b[i] > 126 {
a[i%16] = '.'
} else {
a[i%16] = b[i]
}
if i%16 == 15 {
fmt.Printf(" %s\n", string(a[:]))
}
}
}
func IntToByteArray(num uint64) []byte {
size := int(unsafe.Sizeof(num))
arr := make([]byte, size)
for i := 0; i < size; i++ {
byt := *(*uint8)(unsafe.Pointer(uintptr(unsafe.Pointer(&num)) + uintptr(i)))
arr[i] = byt
}
return arr
}
func sentenceCase(s string) string {
newString := string(s[0])
for i, r := range s[1:] {
if unicode.IsLower(r) && unicode.IsLetter(r) {
newString += string(r)
} else {
if i < len(s)-2 {
nextChar := rune(s[i+2])
previousChar := rune(s[i])
if unicode.IsLower(previousChar) && unicode.IsLetter(previousChar) {
newString += " " + string(r)
} else {
if unicode.IsLower(nextChar) && unicode.IsLetter(nextChar) {
newString += " " + string(r)
} else {
newString += string(r)
}
}
}
}
}
return newString
}
func isDirectory(path string) bool {
fileInfo, err := os.Stat(path)
if err != nil {
return false
}
return fileInfo.IsDir()
}
func parse(filePath string, cfg config) {
// filePath points to a file.
if !isDirectory(filePath) {
parsePE(filePath, cfg)
} else {
// filePath points to a directory,
// walk recursively through all files.
fileList := []string{}
filepath.Walk(filePath, func(path string, f os.FileInfo, err error) error {
if !isDirectory(path) {
fileList = append(fileList, path)
}
return nil
})
for _, file := range fileList {
parsePE(file, cfg)
}
}
}
func parsePE(filename string, cfg config) {
logger := log.NewStdLogger(os.Stdout)
logger = log.NewFilter(logger, log.FilterLevel(log.LevelInfo))
log := log.NewHelper(logger)
log.Infof("parsing filename %s", filename)
data, _ := os.ReadFile(filename)
pe, err := peparser.NewBytes(data, &peparser.Options{
Logger: logger,
DisableCertValidation: false,
Fast: false,
})
if err != nil {
log.Infof("Error while opening file: %s, reason: %s", filename, err)
return
}
defer pe.Close()
err = pe.Parse()
if err != nil {
if err != peparser.ErrDOSMagicNotFound {
log.Infof("Error while parsing file: %s, reason: %s", filename, err)
}
return
}
// Dump all results to disk in JSON format.
// f, err := os.Create("out.json")
// if err != nil {
// return
// }
// defer f.Close()
// f.WriteString(prettyPrint(pe))
if cfg.wantDOSHeader {
DOSHeader := pe.DOSHeader
magic := string(IntToByteArray(uint64(DOSHeader.Magic)))
signature := string(IntToByteArray(uint64(pe.NtHeader.Signature)))
w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
fmt.Print("\n\t------[ DOS Header ]------\n\n")
fmt.Fprintf(w, "Magic:\t 0x%x (%s)\n", DOSHeader.Magic, magic)
fmt.Fprintf(w, "Bytes On Last Page Of File:\t 0x%x\n", DOSHeader.BytesOnLastPageOfFile)
fmt.Fprintf(w, "Pages In File:\t 0x%x\n", DOSHeader.PagesInFile)
fmt.Fprintf(w, "Relocations:\t 0x%x\n", DOSHeader.Relocations)
fmt.Fprintf(w, "Size Of Header:\t 0x%x\n", DOSHeader.SizeOfHeader)
fmt.Fprintf(w, "Min Extra Paragraphs Needed:\t 0x%x\n", DOSHeader.MinExtraParagraphsNeeded)
fmt.Fprintf(w, "Max Extra Paragraphs Needed:\t 0x%x\n", DOSHeader.MaxExtraParagraphsNeeded)
fmt.Fprintf(w, "Initial SS:\t 0x%x\n", DOSHeader.InitialSS)
fmt.Fprintf(w, "Initial SP:\t 0x%x\n", DOSHeader.InitialSP)
fmt.Fprintf(w, "Checksum:\t 0x%x\n", DOSHeader.Checksum)
fmt.Fprintf(w, "Initial IP:\t 0x%x\n", DOSHeader.InitialIP)
fmt.Fprintf(w, "Initial CS:\t 0x%x\n", DOSHeader.InitialCS)
fmt.Fprintf(w, "Address Of Relocation Table:\t 0x%x\n", DOSHeader.AddressOfRelocationTable)
fmt.Fprintf(w, "Overlay Number:\t 0x%x\n", DOSHeader.OverlayNumber)
fmt.Fprintf(w, "OEM Identifier:\t 0x%x\n", DOSHeader.OEMIdentifier)
fmt.Fprintf(w, "OEM Information:\t 0x%x\n", DOSHeader.OEMInformation)
fmt.Fprintf(w, "Address Of New EXE Header:\t 0x%x (%s)\n", DOSHeader.AddressOfNewEXEHeader, signature)
w.Flush()
}
if cfg.wantRichHeader && pe.FileInfo.HasRichHdr {
richHeader := pe.RichHeader
fmt.Printf("\nRICH HEADER\n***********\n")
w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
fmt.Fprintf(w, "\t0x%x\t XOR Key\n", richHeader.XORKey)
fmt.Fprintf(w, "\t0x%x\t DanS offset\n", richHeader.DansOffset)
fmt.Fprintf(w, "\t0x%x\t Checksum\n\n", pe.RichHeaderChecksum())
fmt.Fprintln(w, "ProductID\tMinorCV\tCount\tUnmasked\tMeaning\tVSVersion\t")
for _, compID := range pe.RichHeader.CompIDs {
fmt.Fprintf(w, "0x%x\t0x%x\t0x%x\t0x%x\t%s\t%s\t\n",
compID.ProdID, compID.MinorCV, compID.Count, compID.Unmasked,
peparser.ProdIDtoStr(compID.ProdID), peparser.ProdIDtoVSversion(compID.ProdID))
}
w.Flush()
fmt.Print("\n ---Raw header dump---\n")
hexDump(richHeader.Raw)
}
if cfg.wantNTHeader {
ntHeader := pe.NtHeader.FileHeader
w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
characteristics := strings.Join(ntHeader.Characteristics.String(), " | ")
fmt.Print("\n\t------[ File Header ]------\n\n")
fmt.Fprintf(w, "Machine:\t 0x%x (%s)\n", int(ntHeader.Machine), ntHeader.Machine.String())
fmt.Fprintf(w, "Number Of Sections:\t 0x%x\n", ntHeader.NumberOfSections)
fmt.Fprintf(w, "TimeDateStamp:\t 0x%x (%s)\n", ntHeader.TimeDateStamp, humanizeTimestamp(ntHeader.TimeDateStamp))
fmt.Fprintf(w, "Pointer To Symbol Table:\t 0x%x\n", ntHeader.PointerToSymbolTable)
fmt.Fprintf(w, "Number Of Symbols:\t 0x%x\n", ntHeader.NumberOfSymbols)
fmt.Fprintf(w, "Number Of Symbols:\t 0x%x\n", ntHeader.NumberOfSymbols)
fmt.Fprintf(w, "Size Of Optional Header:\t 0x%x\n", ntHeader.SizeOfOptionalHeader)
fmt.Fprintf(w, "Characteristics:\t 0x%x (%s)\n", ntHeader.Characteristics, characteristics)
w.Flush()
fmt.Print("\n\t------[ Optional Header ]------\n\n")
if pe.Is64 {
oh := pe.NtHeader.OptionalHeader.(peparser.ImageOptionalHeader64)
dllCharacteristics := strings.Join(oh.DllCharacteristics.String(), " | ")
fmt.Fprintf(w, "Magic:\t 0x%x (%s)\n", oh.Magic, pe.PrettyOptionalHeaderMagic())
fmt.Fprintf(w, "Major Linker Version:\t 0x%x\n", oh.MajorLinkerVersion)
fmt.Fprintf(w, "Minor Linker Version:\t 0x%x\n", oh.MinorLinkerVersion)
fmt.Fprintf(w, "Size Of Code:\t 0x%x (%s)\n", oh.SizeOfCode, BytesSize(float64(oh.SizeOfCode)))
fmt.Fprintf(w, "Size Of Initialized Data:\t 0x%x (%s)\n", oh.SizeOfInitializedData,
BytesSize(float64(oh.SizeOfInitializedData)))
fmt.Fprintf(w, "Size Of Uninitialized Data:\t 0x%x (%s)\n", oh.SizeOfUninitializedData,
BytesSize(float64(oh.SizeOfUninitializedData)))
fmt.Fprintf(w, "Address Of Entry Point:\t 0x%x\n", oh.AddressOfEntryPoint)
fmt.Fprintf(w, "Base Of Code:\t 0x%x\n", oh.BaseOfCode)
fmt.Fprintf(w, "Image Base:\t 0x%x\n", oh.ImageBase)
fmt.Fprintf(w, "Section Alignment:\t 0x%x (%s)\n", oh.SectionAlignment,
BytesSize(float64(oh.SectionAlignment)))
fmt.Fprintf(w, "File Alignment:\t 0x%x (%s)\n", oh.FileAlignment,
BytesSize(float64(oh.FileAlignment)))
fmt.Fprintf(w, "Major OS Version:\t 0x%x\n", oh.MajorOperatingSystemVersion)
fmt.Fprintf(w, "Minor OS Version:\t 0x%x\n", oh.MinorOperatingSystemVersion)
fmt.Fprintf(w, "Major Image Version:\t 0x%x\n", oh.MajorImageVersion)
fmt.Fprintf(w, "Minor Image Version:\t 0x%x\n", oh.MinorImageVersion)
fmt.Fprintf(w, "Major Subsystem Version:\t 0x%x\n", oh.MajorSubsystemVersion)
fmt.Fprintf(w, "Minor Subsystem Version:\t 0x%x\n", oh.MinorSubsystemVersion)
fmt.Fprintf(w, "Win32 Version Value:\t 0x%x\n", oh.Win32VersionValue)
fmt.Fprintf(w, "Size Of Image:\t 0x%x (%s)\n", oh.SizeOfImage, BytesSize(float64(oh.SizeOfImage)))
fmt.Fprintf(w, "Size Of Headers:\t 0x%x (%s)\n", oh.SizeOfHeaders, BytesSize(float64(oh.SizeOfHeaders)))
fmt.Fprintf(w, "Checksum:\t 0x%x\n", oh.CheckSum)
fmt.Fprintf(w, "Subsystem:\t 0x%x (%s)\n", uint16(oh.Subsystem), oh.Subsystem.String())
fmt.Fprintf(w, "Dll Characteristics:\t 0x%x (%s)\n", uint16(oh.DllCharacteristics), dllCharacteristics)
fmt.Fprintf(w, "Size Of Stack Reserve:\t 0x%x (%s)\n", oh.SizeOfStackReserve, BytesSize(float64(oh.SizeOfStackReserve)))
fmt.Fprintf(w, "Size Of Stack Commit:\t 0x%x (%s)\n", oh.SizeOfStackCommit, BytesSize(float64(oh.SizeOfStackCommit)))
fmt.Fprintf(w, "Size Of Heap Reserve:\t 0x%x (%s)\n", oh.SizeOfHeapReserve, BytesSize(float64(oh.SizeOfHeapReserve)))
fmt.Fprintf(w, "Size Of Heap Commit:\t 0x%x (%s)\n", oh.SizeOfHeapCommit, BytesSize(float64(oh.SizeOfHeapCommit)))
fmt.Fprintf(w, "Loader Flags:\t 0x%x\n", oh.LoaderFlags)
fmt.Fprintf(w, "Number Of RVA And Sizes:\t 0x%x\n", oh.NumberOfRvaAndSizes)
fmt.Fprintf(w, "\n")
for entry := peparser.ImageDirectoryEntry(0); entry < peparser.ImageNumberOfDirectoryEntries; entry++ {
rva := oh.DataDirectory[entry].VirtualAddress
size := oh.DataDirectory[entry].Size
fmt.Fprintf(w, "%s Table:\t RVA: 0x%0.8x\t Size:0x%0.8x\t\n", entry.String(), rva, size)
}
} else {
oh := pe.NtHeader.OptionalHeader.(peparser.ImageOptionalHeader32)
dllCharacteristics := strings.Join(oh.DllCharacteristics.String(), " | ")
fmt.Fprintf(w, "Magic:\t 0x%x (%s)\n", oh.Magic, pe.PrettyOptionalHeaderMagic())
fmt.Fprintf(w, "Major Linker Version:\t 0x%x\n", oh.MajorLinkerVersion)
fmt.Fprintf(w, "Minor Linker Version:\t 0x%x\n", oh.MinorLinkerVersion)
fmt.Fprintf(w, "Size Of Code:\t 0x%x (%s)\n", oh.SizeOfCode, BytesSize(float64(oh.SizeOfCode)))
fmt.Fprintf(w, "Size Of Initialized Data:\t 0x%x (%s)\n", oh.SizeOfInitializedData,
BytesSize(float64(oh.SizeOfInitializedData)))
fmt.Fprintf(w, "Size Of Uninitialized Data:\t 0x%x (%s)\n", oh.SizeOfUninitializedData,
BytesSize(float64(oh.SizeOfUninitializedData)))
fmt.Fprintf(w, "Address Of Entry Point:\t 0x%x\n", oh.AddressOfEntryPoint)
fmt.Fprintf(w, "Base Of Code:\t 0x%x\n", oh.BaseOfCode)
fmt.Fprintf(w, "Image Base:\t 0x%x\n", oh.ImageBase)
fmt.Fprintf(w, "Section Alignment:\t 0x%x (%s)\n", oh.SectionAlignment,
BytesSize(float64(oh.SectionAlignment)))
fmt.Fprintf(w, "File Alignment:\t 0x%x (%s)\n", oh.FileAlignment,
BytesSize(float64(oh.FileAlignment)))
fmt.Fprintf(w, "Major OS Version:\t 0x%x\n", oh.MajorOperatingSystemVersion)
fmt.Fprintf(w, "Minor OS Version:\t 0x%x\n", oh.MinorOperatingSystemVersion)
fmt.Fprintf(w, "Major Image Version:\t 0x%x\n", oh.MajorImageVersion)
fmt.Fprintf(w, "Minor Image Version:\t 0x%x\n", oh.MinorImageVersion)
fmt.Fprintf(w, "Major Subsystem Version:\t 0x%x\n", oh.MajorSubsystemVersion)
fmt.Fprintf(w, "Minor Subsystem Version:\t 0x%x\n", oh.MinorSubsystemVersion)
fmt.Fprintf(w, "Win32 Version Value:\t 0x%x\n", oh.Win32VersionValue)
fmt.Fprintf(w, "Size Of Image:\t 0x%x (%s)\n", oh.SizeOfImage, BytesSize(float64(oh.SizeOfImage)))
fmt.Fprintf(w, "Size Of Headers:\t 0x%x (%s)\n", oh.SizeOfHeaders, BytesSize(float64(oh.SizeOfHeaders)))
fmt.Fprintf(w, "Checksum:\t 0x%x\n", oh.CheckSum)
fmt.Fprintf(w, "Subsystem:\t 0x%x (%s)\n", uint16(oh.Subsystem), oh.Subsystem.String())
fmt.Fprintf(w, "Dll Characteristics:\t 0x%x (%s)\n", uint16(oh.DllCharacteristics), dllCharacteristics)
fmt.Fprintf(w, "Size Of Stack Reserve:\t 0x%x (%s)\n", oh.SizeOfStackReserve, BytesSize(float64(oh.SizeOfStackReserve)))
fmt.Fprintf(w, "Size Of Stack Commit:\t 0x%x (%s)\n", oh.SizeOfStackCommit, BytesSize(float64(oh.SizeOfStackCommit)))
fmt.Fprintf(w, "Size Of Heap Reserve:\t 0x%x (%s)\n", oh.SizeOfHeapReserve, BytesSize(float64(oh.SizeOfHeapReserve)))
fmt.Fprintf(w, "Size Of Heap Commit:\t 0x%x (%s)\n", oh.SizeOfHeapCommit, BytesSize(float64(oh.SizeOfHeapCommit)))
fmt.Fprintf(w, "Loader Flags:\t 0x%x\n", oh.LoaderFlags)
fmt.Fprintf(w, "Number Of RVA And Sizes:\t 0x%x\n", oh.NumberOfRvaAndSizes)
fmt.Fprintf(w, "\n")
for entry := peparser.ImageDirectoryEntry(0); entry < peparser.ImageNumberOfDirectoryEntries; entry++ {
rva := oh.DataDirectory[entry].VirtualAddress
size := oh.DataDirectory[entry].Size
fmt.Fprintf(w, "%s Table:\t RVA: 0x%0.8x\t Size:0x%0.8x\t\n", entry.String(), rva, size)
}
}
w.Flush()
}
if cfg.wantCOFF && pe.FileInfo.HasCOFF {
fmt.Printf("\nCOFF\n****\n")
w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
fmt.Fprintln(w, "Name\tValue\tSectionNumber\tType\tStorageClass\tNumberOfAuxSymbols\t")
for _, sym := range pe.COFF.SymbolTable {
symName, _ := sym.String(pe)
fmt.Fprintf(w, "%s\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t\n",
symName, sym.Value, sym.SectionNumber,
sym.Type, sym.StorageClass, sym.NumberOfAuxSymbols)
}
w.Flush()
}
if cfg.wantSections && pe.FileInfo.HasSections {
w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
for i, sec := range pe.Sections {
hdr := sec.Header
fmt.Printf("\n\t------[ Section Header #%d ]------\n\n", i)
fmt.Fprintf(w, "Name:\t %v (%s)\n", hdr.Name, sec.String())
fmt.Fprintf(w, "Virtual Size:\t 0x%x (%s)\n", hdr.VirtualSize,
BytesSize(float64(hdr.VirtualSize)))
fmt.Fprintf(w, "Virtual Address:\t 0x%x\n", hdr.VirtualAddress)
fmt.Fprintf(w, "Size Of Raw Data Size:\t 0x%x (%s)\n", hdr.SizeOfRawData,
BytesSize(float64(hdr.SizeOfRawData)))
fmt.Fprintf(w, "Pointer To Raw Data:\t 0x%x\n", hdr.PointerToRawData)
fmt.Fprintf(w, "Pointer To Relocations:\t 0x%x\n", hdr.PointerToRelocations)
fmt.Fprintf(w, "Pointer To Line Numbers:\t 0x%x\n", hdr.PointerToLineNumbers)
fmt.Fprintf(w, "Number Of Relocations:\t 0x%x\n", hdr.NumberOfRelocations)
fmt.Fprintf(w, "Number Of Line Numbers:\t 0x%x\n", hdr.NumberOfLineNumbers)
fmt.Fprintf(w, "Characteristics:\t 0x%x (%s)\n", hdr.Characteristics,
strings.Join(sec.PrettySectionFlags(), " | "))
fmt.Fprintf(w, "Entropy:\t %f\n", sec.CalculateEntropy(pe))
w.Flush()
fmt.Fprintf(w, "\n")
hexDumpSize(sec.Data(0, hdr.PointerToRawData, pe), 128)
}
}
if cfg.wantImport && pe.FileInfo.HasImport {
fmt.Printf("\nIMPORTS\n********\n")
w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
for _, imp := range pe.Imports {
desc := imp.Descriptor
fmt.Printf("\n\t------[ %s ]------\n\n", imp.Name)
fmt.Fprintf(w, "Name:\t 0x%x\n", desc.Name)
fmt.Fprintf(w, "Original First Thunk:\t 0x%x\n", desc.OriginalFirstThunk)
fmt.Fprintf(w, "First Thunk:\t 0x%x\n", desc.FirstThunk)
fmt.Fprintf(w, "TimeDateStamp:\t 0x%x (%s\n", desc.TimeDateStamp,
humanizeTimestamp(desc.TimeDateStamp))
fmt.Fprintf(w, "Forwarder Chain:\t 0x%x\n", desc.ForwarderChain)
fmt.Fprintf(w, "\n")
fmt.Fprintln(w, "Name\tThunkRVA\tThunkValue\tOriginalThunkRVA\tOriginalThunkValue\tHint\t")
for _, impFunc := range imp.Functions {
fmt.Fprintf(w, "%s\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t\n",
impFunc.Name, impFunc.ThunkRVA, impFunc.ThunkValue,
impFunc.OriginalThunkRVA, impFunc.OriginalThunkValue, impFunc.Hint)
}
w.Flush()
}
}
if cfg.wantExport && pe.FileInfo.HasExport {
fmt.Printf("\nEXPORTS\n********\n")
w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
expDir := pe.Export.Struct
fmt.Printf("\n\t------[ %s ]------\n\n", pe.Export.Name)
fmt.Fprintf(w, "Characteristics:\t 0x%x\n", expDir.Characteristics)
fmt.Fprintf(w, "TimeDateStamp:\t 0x%x (%s\n", expDir.TimeDateStamp,
humanizeTimestamp(expDir.TimeDateStamp))
fmt.Fprintf(w, "Major Version:\t 0x%x\n", expDir.MajorVersion)
fmt.Fprintf(w, "Minor Version:\t 0x%x\n", expDir.MinorVersion)
fmt.Fprintf(w, "Name:\t 0x%x\n", expDir.Name)
fmt.Fprintf(w, "Base:\t 0x%x\n", expDir.Base)
fmt.Fprintf(w, "Number Of Functions:\t 0x%x\n", expDir.NumberOfFunctions)
fmt.Fprintf(w, "Number Of Names:\t 0x%x\n", expDir.NumberOfNames)
fmt.Fprintf(w, "Address Of Functions:\t 0x%x\n", expDir.AddressOfFunctions)
fmt.Fprintf(w, "Address Of Names:\t 0x%x\n", expDir.AddressOfNames)
fmt.Fprintf(w, "Address Of Name Ordinals:\t 0x%x\n", expDir.AddressOfNameOrdinals)
fmt.Fprintf(w, "\n")
fmt.Fprintln(w, "Name\tOrdinal\tNameRVA\tFunctionRVA\tForwardedTo\t")
for _, exp := range pe.Export.Functions {
fmt.Fprintf(w, "%s\t0x%x\t0x%x\t0x%x\t0x%x\t%s\t\n",
exp.Name, exp.Ordinal, exp.NameRVA, exp.FunctionRVA, exp.ForwarderRVA, exp.Forwarder)
}
w.Flush()
}
if cfg.wantResource && pe.FileInfo.HasResource {
var printRsrcDir func(rsrcDir peparser.ResourceDirectory)
padding := 0
printRsrcDataEntry := func(entry peparser.ResourceDataEntry) {
padding++
w := tabwriter.NewWriter(os.Stdout, 1, 1, padding, ' ', 0)
imgRsrcDataEntry := entry.Struct
fmt.Fprintf(w, "\n\t\u27A1 Resource Data Entry\n\t")
fmt.Fprintf(w, "|- Offset To Data: 0x%x\n\t", imgRsrcDataEntry.OffsetToData)
fmt.Fprintf(w, "|- Size: 0x%x\n\t", imgRsrcDataEntry.Size)
fmt.Fprintf(w, "|- Code Page: 0x%x\n\t", imgRsrcDataEntry.CodePage)
fmt.Fprintf(w, "|- Reserved: 0x%x\n\t", imgRsrcDataEntry.Reserved)
fmt.Fprintf(w, "|- Language: %d (%s)\n\t", entry.Lang, entry.Lang.String())
fmt.Fprintf(w, "|- Sub-language: %s\n\t", peparser.PrettyResourceLang(entry.Lang, int(entry.SubLang)))
w.Flush()
padding--
}
printRsrcDir = func(rsrcDir peparser.ResourceDirectory) {
padding++
w := tabwriter.NewWriter(os.Stdout, 1, 1, padding, ' ', 0)
imgRsrcDir := rsrcDir.Struct
fmt.Fprintf(w, "\n\t\u27A1 Resource Directory\n\t")
fmt.Fprintf(w, "|- Characteristics: 0x%x\n\t", imgRsrcDir.Characteristics)
fmt.Fprintf(w, "|- TimeDateStamp: 0x%x\n\t", imgRsrcDir.TimeDateStamp)
fmt.Fprintf(w, "|- Major Version: 0x%x\n\t", imgRsrcDir.MajorVersion)
fmt.Fprintf(w, "|- Minor Version: 0x%x\n\t", imgRsrcDir.MinorVersion)
fmt.Fprintf(w, "|- Number Of Named Entries: 0x%x\n\t", imgRsrcDir.NumberOfNamedEntries)
fmt.Fprintf(w, "|- Number Of ID Entries: 0x%x\n\t", imgRsrcDir.NumberOfIDEntries)
fmt.Fprintf(w, "|----------------------------------\n\t")
padding++
w.Flush()
w = tabwriter.NewWriter(os.Stdout, 1, 1, padding, ' ', 0)
for i, entry := range rsrcDir.Entries {
fmt.Fprintf(w, "\t|- \u27A1 Resource Directory Entry %d, ID: %d", i+1, entry.ID)
// Print the interpretation of a resource ID only in root node.
if padding == 2 {
if entry.ID <= peparser.RTManifest {
fmt.Fprintf(w, " (%s)", peparser.ResourceType(entry.ID).String())
}
}
fmt.Fprintf(w, "\n\t|- Name: 0x%x\n\t", entry.Struct.Name)
if entry.Name != "" {
fmt.Fprintf(w, " (%s)", entry.Name)
}
fmt.Fprintf(w, "|- Offset To Data: 0x%x\t", entry.Struct.OffsetToData)
fmt.Fprintf(w, "\n\t|----------------------------------\t")
w.Flush()
if entry.IsResourceDir {
printRsrcDir(entry.Directory)
} else {
printRsrcDataEntry(entry.Data)
}
}
padding -= 2
}
fmt.Printf("\nRESOURCES\n**********\n")
printRsrcDir(pe.Resources)
versionInfo, err := pe.ParseVersionResources()
if err != nil {
log.Errorf("failed to parse version resources: %v", err)
} else {
fmt.Printf("\nVersion Info: %v", prettyPrint(versionInfo))
}
}
if cfg.wantException && pe.FileInfo.HasException {
fmt.Printf("\nEXCEPTIONS\n***********\n")
for _, exception := range pe.Exceptions {
entry := exception.RuntimeFunction
fmt.Printf("\n\u27A1 BeginAddress: 0x%x EndAddress:0x%x UnwindInfoAddress:0x%x\t\n",
entry.BeginAddress, entry.EndAddress, entry.UnwindInfoAddress)
ui := exception.UnwindInfo
handlerFlags := peparser.PrettyUnwindInfoHandlerFlags(ui.Flags)
prettyFlags := strings.Join(handlerFlags, ",")
fmt.Printf("|- Version: 0x%x\n", ui.Version)
fmt.Printf("|- Flags: 0x%x", ui.Flags)
if ui.Flags == 0 {
fmt.Print(" (None)\n")
} else {
fmt.Printf(" (%s)\n", prettyFlags)
}
fmt.Printf("|- Size Of Prolog: 0x%x\n", ui.SizeOfProlog)
fmt.Printf("|- Count Of Codes: 0x%x\n", ui.CountOfCodes)
fmt.Printf("|- Exception Handler: 0x%x\n", ui.ExceptionHandler)
fmt.Print("|- Unwind codes:\n")
for _, uc := range ui.UnwindCodes {
fmt.Printf("|- * %.2x: %s, %s\n", uc.CodeOffset,
uc.UnwindOp.String(), uc.Operand)
}
}
}
if cfg.wantCertificate && pe.FileInfo.HasCertificate {
fmt.Printf("\nSECURITY\n*********\n")
cert := pe.Certificates
w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
fmt.Fprintln(w, "Length\tRevision\tCertificateType\t")
fmt.Fprintf(w, "0x%x\t0x%x\t0x%x\t\n", cert.Header.Length, cert.Header.Revision,
cert.Header.CertificateType)
w.Flush()
fmt.Print("\n ---Raw Certificate dump---\n")
hexDump(cert.Raw)
for _, cert := range cert.Certificates {
fmt.Print("\n---Certificate ---\n\n")
fmt.Fprintf(w, "Issuer Name:\t %s\n", cert.Info.Issuer)
fmt.Fprintf(w, "Subject Name:\t %s\n", cert.Info.Subject)
fmt.Fprintf(w, "Serial Number:\t %x\n", cert.Info.SerialNumber)
fmt.Fprintf(w, "Validity From:\t %s to %s\n", cert.Info.NotBefore.String(), cert.Info.NotAfter.String())
fmt.Fprintf(w, "Signature Algorithm:\t %s\n", cert.Info.SignatureAlgorithm.String())
fmt.Fprintf(w, "PublicKey Algorithm:\t %s\n", cert.Info.PublicKeyAlgorithm.String())
fmt.Fprintf(w, "Certificate valid:\t %v\n", cert.Verified)
fmt.Fprintf(w, "Signature valid:\t %v\n", cert.SignatureValid)
w.Flush()
}
// Calculate the PE authentihash.
pe.Authentihash()
}
if cfg.wantReloc && pe.FileInfo.HasReloc {
fmt.Printf("\nRELOCATIONS\n***********\n")
for _, reloc := range pe.Relocations {
fmt.Printf("\n\u27A1 Virtual Address: 0x%x | Size Of Block:0x%x | Entries Count:0x%x\t\n",
reloc.Data.VirtualAddress, reloc.Data.SizeOfBlock, len(reloc.Entries))
fmt.Print("|- Entries:\n")
for _, relocEntry := range reloc.Entries {
fmt.Printf("|- Data: 0x%x | Offset: 0x%x | Type:0x%x (%s)\n", relocEntry.Data,
relocEntry.Offset, relocEntry.Type, relocEntry.Type.String(pe))
}
}
}
if cfg.wantDebug && pe.FileInfo.HasDebug {
fmt.Printf("\nDEBUGS\n*******\n")
w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
for _, debug := range pe.Debugs {
imgDbgDir := debug.Struct
fmt.Fprintf(w, "\n\t------[ %s ]------\n", debug.Type)
fmt.Fprintf(w, "Characteristics:\t 0x%x\n", imgDbgDir.Characteristics)
fmt.Fprintf(w, "TimeDateStamp:\t 0x%x (%s)\n", imgDbgDir.TimeDateStamp,
humanizeTimestamp(imgDbgDir.TimeDateStamp))
fmt.Fprintf(w, "Major Version:\t 0x%x\n", imgDbgDir.MajorVersion)
fmt.Fprintf(w, "Minor Version:\t 0x%x\n", imgDbgDir.MinorVersion)
fmt.Fprintf(w, "Type:\t 0x%x\n", imgDbgDir.Type)
fmt.Fprintf(w, "Size Of Data:\t 0x%x (%s)\n", imgDbgDir.SizeOfData,
BytesSize(float64(imgDbgDir.SizeOfData)))
fmt.Fprintf(w, "Address Of Raw Data:\t 0x%x\n", imgDbgDir.AddressOfRawData)
fmt.Fprintf(w, "Pointer To Raw Data:\t 0x%x\n", imgDbgDir.PointerToRawData)
fmt.Fprintf(w, "\n")
switch imgDbgDir.Type {
case peparser.ImageDebugTypeCodeView:
debugSignature, err := pe.ReadUint32(imgDbgDir.PointerToRawData)
if err != nil {
continue
}
switch debugSignature {
case peparser.CVSignatureRSDS:
pdb := debug.Info.(peparser.CVInfoPDB70)
fmt.Fprintf(w, "CV Signature:\t 0x%x (%s)\n", pdb.CVSignature,
pdb.CVSignature.String())
fmt.Fprintf(w, "Signature:\t %s\n", pdb.Signature.String())
fmt.Fprintf(w, "Age:\t 0x%x\n", pdb.Age)
fmt.Fprintf(w, "PDB FileName:\t %s\n", pdb.PDBFileName)
case peparser.CVSignatureNB10:
pdb := debug.Info.(peparser.CVInfoPDB20)
fmt.Fprintf(w, "CV Header Signature:\t 0x%x (%s)\n",
pdb.CVHeader.Signature, pdb.CVHeader.Signature.String())
fmt.Fprintf(w, "CV Header Offset:\t 0x%x\n", pdb.CVHeader.Offset)
fmt.Fprintf(w, "Signature:\t 0x%x (%s)\n", pdb.Signature,
humanizeTimestamp(pdb.Signature))
fmt.Fprintf(w, "Age:\t 0x%x\n", pdb.Age)
fmt.Fprintf(w, "PDBFileName:\t %s\n", pdb.PDBFileName)
}
case peparser.ImageDebugTypePOGO:
pogo := debug.Info.(peparser.POGO)
if len(pogo.Entries) > 0 {
fmt.Fprintf(w, "Signature:\t 0x%x (%s)\n\n", pogo.Signature,
pogo.Signature.String())
fmt.Fprintln(w, "RVA\tSize\tName\tDescription\t")
fmt.Fprintln(w, "---\t----\t----\t-----------\t")
for _, pogoEntry := range pogo.Entries {
fmt.Fprintf(w, "0x%x\t0x%x\t%s\t%s\t\n", pogoEntry.RVA,
pogoEntry.Size, pogoEntry.Name,
peparser.SectionAttributeDescription(pogoEntry.Name))
}
}
case peparser.ImageDebugTypeRepro:
repro := debug.Info.(peparser.REPRO)
fmt.Fprintf(w, "Hash:\t %x\n", repro.Hash)
fmt.Fprintf(w, "Size:\t 0x%x (%s)\n", repro.Size, BytesSize(float64(repro.Size)))
case peparser.ImageDebugTypeExDllCharacteristics:
exDllCharacteristics := debug.Info.(peparser.DllCharacteristicsExType)
fmt.Fprintf(w, "Value:\t %d (%s)\n", exDllCharacteristics,
exDllCharacteristics.String())
case peparser.ImageDebugTypeVCFeature:
VCFeature := debug.Info.(peparser.VCFeature)
fmt.Fprintf(w, "Pre VC11:\t 0x%x\n", VCFeature.PreVC11)
fmt.Fprintf(w, "C/C++:\t 0x%x\n", VCFeature.CCpp)
fmt.Fprintf(w, "/GS:\t 0x%x\n", VCFeature.Gs)
fmt.Fprintf(w, "/sdl:\t 0x%x\n", VCFeature.Sdl)
fmt.Fprintf(w, "GuardN:\t 0x%x\n", VCFeature.GuardN)
case peparser.ImageDebugTypeFPO:
fpo := debug.Info.([]peparser.FPOData)
if len(fpo) > 0 {
fmt.Fprintln(w, "OffsetStart\tProcSize\tNumLocals\tParamsSize\tPrologLength\tSavedRegsCount\tHasSEH\tUseBP\tReserved\tFrameType\t")
fmt.Fprintln(w, "------\t------\t------\t------\t------\t------\t------\t------\t------\t------\t")
for _, fpoData := range fpo {
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",
fpoData.OffsetStart, fpoData.ProcSize, fpoData.NumLocals,
fpoData.ParamsSize, fpoData.PrologLength,
fpoData.SavedRegsCount, fpoData.HasSEH, fpoData.UseBP,
fpoData.Reserved, fpoData.FrameType, fpoData.FrameType.String())
}
}
}
}
w.Flush()
}
if cfg.wantBoundImp && pe.FileInfo.HasBoundImp {
fmt.Printf("\nBOUND IMPORTS\n************\n")
w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
for _, bndImp := range pe.BoundImports {
fmt.Printf("\n\t------[ %s ]------\n\n", bndImp.Name)
fmt.Fprintf(w, "TimeDateStamp:\t 0x%x (%s)\n", bndImp.Struct.TimeDateStamp,
humanizeTimestamp(bndImp.Struct.TimeDateStamp))
fmt.Fprintf(w, "Offset Module Name:\t 0x%x\n", bndImp.Struct.OffsetModuleName)
fmt.Fprintf(w, "# Module Forwarder Refs:\t 0x%x\n", bndImp.Struct.NumberOfModuleForwarderRefs)
fmt.Fprintf(w, "\n")
if len(bndImp.ForwardedRefs) > 0 {
fmt.Fprintln(w, "Name\tTimeDateStamp\tOffsetModuleName\tReserved\t")
for _, fr := range bndImp.ForwardedRefs {
fmt.Fprintf(w, "%s\t0x%x\t0x%x\t0x%x\t\n", fr.Name,
fr.Struct.TimeDateStamp, fr.Struct.OffsetModuleName,
fr.Struct.Reserved)
}
}
w.Flush()
}
}
if cfg.wantTLS && pe.FileInfo.HasTLS {
fmt.Printf("\nTLS\n*****\n\n")
tls := pe.TLS
w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
if pe.Is64 {
imgTLSDirectory64 := tls.Struct.(peparser.ImageTLSDirectory64)
fmt.Fprintf(w, "Start Address Of Raw Data:\t 0x%x\n", imgTLSDirectory64.StartAddressOfRawData)
fmt.Fprintf(w, "End Address Of Raw Data:\t 0x%x\n", imgTLSDirectory64.EndAddressOfRawData)
fmt.Fprintf(w, "Address Of Index:\t %x\n", imgTLSDirectory64.AddressOfIndex)
fmt.Fprintf(w, "Address Of CallBacks:\t 0x%x\n", imgTLSDirectory64.AddressOfCallBacks)
fmt.Fprintf(w, "Size Of Zero Fill:\t 0x%x\n", imgTLSDirectory64.SizeOfZeroFill)
fmt.Fprintf(w, "Characteristics:\t 0x%x (%s)\n", imgTLSDirectory64.Characteristics,
imgTLSDirectory64.Characteristics.String())
fmt.Fprintf(w, "Callbacks:\n")
if tls.Callbacks != nil && len(tls.Callbacks.([]uint64)) > 0 {
for _, callback := range tls.Callbacks.([]uint64) {
fmt.Fprintf(w, "0x%x\t\n", callback)
}
}
} else {
imgTLSDirectory32 := tls.Struct.(peparser.ImageTLSDirectory32)
fmt.Fprintf(w, "Start Address Of Raw Data:\t 0x%x\n", imgTLSDirectory32.StartAddressOfRawData)
fmt.Fprintf(w, "End Address Of Raw Data:\t 0x%x\n", imgTLSDirectory32.EndAddressOfRawData)
fmt.Fprintf(w, "Address Of Index:\t %x\n", imgTLSDirectory32.AddressOfIndex)
fmt.Fprintf(w, "Address Of CallBacks:\t 0x%x\n", imgTLSDirectory32.AddressOfCallBacks)
fmt.Fprintf(w, "Size Of Zero Fill:\t 0x%x\n", imgTLSDirectory32.SizeOfZeroFill)
fmt.Fprintf(w, "Characteristics:\t 0x%x (%s)\n", imgTLSDirectory32.Characteristics,
imgTLSDirectory32.Characteristics.String())
fmt.Fprintf(w, "Callbacks:\n")
if tls.Callbacks != nil && len(tls.Callbacks.([]uint32)) > 0 {
for _, callback := range tls.Callbacks.([]uint32) {
fmt.Fprintf(w, "0x%x\t\n", callback)
}
}
}
w.Flush()
}
if cfg.wantLoadCfg && pe.FileInfo.HasLoadCFG {
fmt.Printf("\nLOAD CONFIG\n************\n\n")
loadConfig := pe.LoadConfig
w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.TabIndent)
v := reflect.ValueOf(loadConfig.Struct)
typeOfS := v.Type()
imgLoadConfigDirectorySize := v.Field(0).Interface().(uint32)
tmp := uint32(0)
for i := 0; i < v.NumField(); i++ {
// Do not print the fields of the image load config directory structure
// that does not belong to it.
tmp += uint32(binary.Size((v.Field(i).Interface())))
if tmp > imgLoadConfigDirectorySize {
break
}
fmt.Fprintf(w, " %s\t : 0x%v\n", sentenceCase(typeOfS.Field(i).Name),
v.Field(i).Interface())
}
w.Flush()
}
if cfg.wantDelayImp && pe.FileInfo.HasDelayImp {
fmt.Printf("\nDELAY IMPORTS\n**************\n")
w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
for _, imp := range pe.DelayImports {
desc := imp.Descriptor
fmt.Printf("\n\t------[ %s ]------\n\n", imp.Name)
fmt.Fprintf(w, "Attributes:\t 0x%x\n", desc.Attributes)
fmt.Fprintf(w, "Name:\t 0x%x\n", desc.Name)
fmt.Fprintf(w, "Module Handle RVA:\t 0x%x\n", desc.ModuleHandleRVA)
fmt.Fprintf(w, "Import Address Table RVA:\t 0x%x\n", desc.ImportAddressTableRVA)
fmt.Fprintf(w, "Import Name Table RVA:\t 0x%x\n", desc.ImportNameTableRVA)
fmt.Fprintf(w, "Bound Import Address Table RVA:\t 0x%x\n", desc.BoundImportAddressTableRVA)
fmt.Fprintf(w, "Unload Information Table RVA:\t 0x%x\n", desc.UnloadInformationTableRVA)
fmt.Fprintf(w, "TimeDateStamp:\t 0x%x (%s)\n", desc.TimeDateStamp,
humanizeTimestamp(desc.TimeDateStamp))
fmt.Fprintf(w, "\n")
fmt.Fprintln(w, "Name\tThunkRVA\tThunkValue\tOriginalThunkRVA\tOriginalThunkValue\tHint\t")
for _, fn := range imp.Functions {
fmt.Fprintf(w, "%s\t0x%x\t0x%x\t0x%x\t0x%x\t0x%x\t\n",
fn.Name, fn.ThunkRVA, fn.ThunkValue,
fn.OriginalThunkRVA, fn.OriginalThunkValue, fn.Hint)
}
w.Flush()
}
}
if cfg.wantIAT && pe.FileInfo.HasIAT {
fmt.Printf("\nIAT\n****\n\n")
w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
fmt.Fprintln(w, "Index\tRVA\tValue\tMeaning\t")
for _, entry := range pe.IAT {
fmt.Fprintf(w, "0x%x\t0x%x\t%v\t%s\t\n",
entry.Index, entry.Rva, entry.Value, entry.Meaning)
}
w.Flush()
}
if cfg.wantCLR && pe.FileInfo.HasCLR {
fmt.Printf("\nCLR\n****\n")
fmt.Print("\n\t------[ CLR Header ]------\n\n")
clr := pe.CLR
w := tabwriter.NewWriter(os.Stdout, 1, 1, 3, ' ', tabwriter.AlignRight)
clrHdr := clr.CLRHeader
flags := strings.Join(clrHdr.Flags.String(), " | ")
fmt.Fprintf(w, "Size Of Header:\t 0x%x\n", clrHdr.Cb)
fmt.Fprintf(w, "Major Runtime Version:\t 0x%x\n", clrHdr.MajorRuntimeVersion)
fmt.Fprintf(w, "Minor Runtime Version:\t 0x%x\n", clrHdr.MinorRuntimeVersion)
fmt.Fprintf(w, "MetaData RVA:\t 0x%x\n", clrHdr.MetaData.VirtualAddress)
fmt.Fprintf(w, "MetaData Size:\t 0x%x\n", clrHdr.MetaData.Size)
fmt.Fprintf(w, "Flags:\t 0x%x (%v)\n", clrHdr.Flags, flags)
fmt.Fprintf(w, "EntryPoint RVA or Token:\t 0x%x\n", clrHdr.EntryPointRVAorToken)
fmt.Fprintf(w, "Resources RVA:\t 0x%x\n", clrHdr.Resources.VirtualAddress)
fmt.Fprintf(w, "Resources Size:\t 0x%x (%s)\n", clrHdr.Resources.Size, BytesSize(float64(clrHdr.Resources.Size)))
fmt.Fprintf(w, "Strong Name Signature RVA:\t 0x%x\n", clrHdr.StrongNameSignature.VirtualAddress)
fmt.Fprintf(w, "Strong Name Signature Size:\t 0x%x (%s)\n", clrHdr.StrongNameSignature.Size, BytesSize(float64(clrHdr.StrongNameSignature.Size)))
fmt.Fprintf(w, "Code Manager Table RVA:\t 0x%x\n", clrHdr.CodeManagerTable.VirtualAddress)
fmt.Fprintf(w, "Code Manager Table Size:\t 0x%x (%s)\n", clrHdr.CodeManagerTable.Size, BytesSize(float64(clrHdr.CodeManagerTable.Size)))
fmt.Fprintf(w, "VTable Fixups RVA:\t 0x%x\n", clrHdr.VTableFixups.VirtualAddress)
fmt.Fprintf(w, "VTable Fixups Size:\t 0x%x (%s)\n", clrHdr.VTableFixups.Size, BytesSize(float64(clrHdr.VTableFixups.Size)))
fmt.Fprintf(w, "Export Address Table Jumps RVA:\t 0x%x\n", clrHdr.ExportAddressTableJumps.VirtualAddress)
fmt.Fprintf(w, "Export Address Table Jumps Size:\t 0x%x (%s)\n", clrHdr.ExportAddressTableJumps.Size, BytesSize(float64(clrHdr.ExportAddressTableJumps.Size)))
fmt.Fprintf(w, "Managed Native Header RVA:\t 0x%x\n", clrHdr.ManagedNativeHeader.VirtualAddress)
fmt.Fprintf(w, "Managed Native Header Size:\t 0x%x (%s)\n", clrHdr.ManagedNativeHeader.Size, BytesSize(float64(clrHdr.ManagedNativeHeader.Size)))
w.Flush()
fmt.Print("\n\t------[ MetaData Header ]------\n\n")
mdHdr := clr.MetadataHeader
fmt.Fprintf(w, "Signature:\t 0x%x (%s)\n", mdHdr.Signature,
string(IntToByteArray(uint64(mdHdr.Signature))))
fmt.Fprintf(w, "Major Version:\t 0x%x\n", mdHdr.MajorVersion)
fmt.Fprintf(w, "Minor Version:\t 0x%x\n", mdHdr.MinorVersion)
fmt.Fprintf(w, "Extra Data:\t 0x%x\n", mdHdr.ExtraData)
fmt.Fprintf(w, "Version String Length:\t 0x%x\n", mdHdr.VersionString)
fmt.Fprintf(w, "Version String:\t %s\n", mdHdr.Version)
fmt.Fprintf(w, "Flags:\t 0x%x\n", mdHdr.Flags)
fmt.Fprintf(w, "Streams Count:\t 0x%x\n", mdHdr.Streams)
w.Flush()
fmt.Print("\n\t------[ MetaData Streams ]------\n\n")
for _, sh := range clr.MetadataStreamHeaders {
fmt.Fprintf(w, "Stream Name:\t %s\n", sh.Name)
fmt.Fprintf(w, "Offset:\t 0x%x\n", sh.Offset)
fmt.Fprintf(w, "Size:\t 0x%x (%s)\n", sh.Size, BytesSize(float64(sh.Size)))
w.Flush()
fmt.Print("\n ---Stream Content---\n")
hexDumpSize(clr.MetadataStreams[sh.Name], 128)
fmt.Print("\n")
}
fmt.Print("\n\t------[ MetaData Tables Stream Header ]------\n\n")
mdTablesStreamHdr := clr.MetadataTablesStreamHeader
fmt.Fprintf(w, "Reserved:\t 0x%x\n", mdTablesStreamHdr.Reserved)
fmt.Fprintf(w, "Major Version:\t 0x%x\n", mdTablesStreamHdr.MajorVersion)
fmt.Fprintf(w, "Minor Version:\t 0x%x\n", mdTablesStreamHdr.MinorVersion)
fmt.Fprintf(w, "Heaps:\t 0x%x\n", mdTablesStreamHdr.Heaps)
fmt.Fprintf(w, "RID:\t 0x%x\n", mdTablesStreamHdr.RID)
fmt.Fprintf(w, "MaskValid:\t 0x%x\n", mdTablesStreamHdr.MaskValid)
fmt.Fprintf(w, "Sorted:\t 0x%x\n", mdTablesStreamHdr.Sorted)
w.Flush()
fmt.Print("\n\t------[ MetaData Tables ]------\n\n")
mdTables := clr.MetadataTables
for _, mdTable := range mdTables {
fmt.Fprintf(w, "Name:\t %s | Items Count:\t 0x%x\n", mdTable.Name, mdTable.CountCols)
}
w.Flush()
for table, modTable := range pe.CLR.MetadataTables {
switch table {
case peparser.Module:
fmt.Print("\n\t[Modules]\n\t---------\n")
modTableRows := modTable.Content.([]peparser.ModuleTableRow)
for _, modTableRow := range modTableRows {
modName := pe.GetStringFromData(modTableRow.Name, pe.CLR.MetadataStreams["#Strings"])
Mvid := pe.GetStringFromData(modTableRow.Mvid, pe.CLR.MetadataStreams["#GUID"])
MvidStr := hex.EncodeToString(Mvid)
fmt.Fprintf(w, "Generation:\t 0x%x\n", modTableRow.Generation)
fmt.Fprintf(w, "Name:\t 0x%x (%s)\n", modTableRow.Name, string(modName))
fmt.Fprintf(w, "Mvid:\t 0x%x (%s)\n", modTableRow.Mvid, MvidStr)
fmt.Fprintf(w, "EncID:\t 0x%x\n", modTableRow.EncID)
fmt.Fprintf(w, "EncBaseID:\t 0x%x\n", modTableRow.EncBaseID)
}
w.Flush()
}
}
}
// Get file type.
if pe.IsEXE() {
log.Debug("File is Exe")
}
if pe.IsDLL() {
log.Debug("File is DLL")
}
if pe.IsDriver() {
log.Debug("File is Driver")
}
// Calculate the PE checksum.
pe.Checksum()
fmt.Print("\n")
}
================================================
FILE: cmd/main.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.
package main
import (
"flag"
"fmt"
"os"
"runtime"
)
type config struct {
wantDOSHeader bool
wantRichHeader bool
wantNTHeader bool
wantCOFF bool
wantDataDirs bool
wantSections bool
wantExport bool
wantImport bool
wantResource bool
wantException bool
wantCertificate bool
wantReloc bool
wantDebug bool
wantTLS bool
wantLoadCfg bool
wantBoundImp bool
wantIAT bool
wantDelayImp bool
wantCLR bool
}
func main() {
dumpCmd := flag.NewFlagSet("dump", flag.ExitOnError)
dumpDOSHdr := dumpCmd.Bool("dosheader", false, "Dump DOS header")
dumpRichHdr := dumpCmd.Bool("richheader", false, "Dump Rich header")
dumpNTHdr := dumpCmd.Bool("ntheader", false, "Dump NT header")
dumpCOFF := dumpCmd.Bool("coff", false, "Dump COFF symbols")
dumpDirs := dumpCmd.Bool("directories", false, "Dump data directories")
dumpSections := dumpCmd.Bool("sections", false, "Dump sections")
dumpExport := dumpCmd.Bool("export", false, "Dump export table")
dumpImport := dumpCmd.Bool("import", false, "Dump import table")
dumpResource := dumpCmd.Bool("resource", false, "Dump resource table")
dumpException := dumpCmd.Bool("exception", false, "Dump exception table")
dumpCertificate := dumpCmd.Bool("cert", false, "Dump certificate directory")
dumpReloc := dumpCmd.Bool("reloc", false, "Dump relocation table")
dumpDebug := dumpCmd.Bool("debug", false, "Dump debug infos")
dumpTLS := dumpCmd.Bool("tls", false, "Dump TLS")
dumpLoadCfg := dumpCmd.Bool("loadconfig", false, "Dump load configuration table")
dumpBoundImport := dumpCmd.Bool("bound", false, "Dump bound import table")
dumpIAT := dumpCmd.Bool("iat", false, "Dump IAT")
dumpDelayedImport := dumpCmd.Bool("delay", false, "Dump delay import descriptor")
dumpCLR := dumpCmd.Bool("clr", false, "Dump CLR")
dumpCmd.Usage = func() {
fmt.Fprintf(os.Stderr, "Usage: pedumper dump [flags] <file-or-directory>\n\nFlags:\n")
dumpCmd.PrintDefaults()
}
if len(os.Args) < 2 {
showHelp()
}
switch os.Args[1] {
case "dump":
dumpCmd.Parse(os.Args[2:])
args := dumpCmd.Args()
if len(args) == 0 {
fmt.Fprintf(os.Stderr, "Error: missing file or directory path\n\n")
dumpCmd.Usage()
os.Exit(1)
}
filePath := args[0]
// If no flags are specified, dump everything.
noFlagsSet := true
dumpCmd.Visit(func(f *flag.Flag) { noFlagsSet = false })
cfg := config{
wantDOSHeader: *dumpDOSHdr || noFlagsSet,
wantRichHeader: *dumpRichHdr || noFlagsSet,
wantNTHeader: *dumpNTHdr || noFlagsSet,
wantCOFF: *dumpCOFF || noFlagsSet,
wantDataDirs: *dumpDirs || noFlagsSet,
wantSections: *dumpSections || noFlagsSet,
wantExport: *dumpExport || noFlagsSet,
wantImport: *dumpImport || noFlagsSet,
wantResource: *dumpResource || noFlagsSet,
wantException: *dumpException || noFlagsSet,
wantCertificate: *dumpCertificate || noFlagsSet,
wantReloc: *dumpReloc || noFlagsSet,
wantDebug: *dumpDebug || noFlagsSet,
wantTLS: *dumpTLS || noFlagsSet,
wantLoadCfg: *dumpLoadCfg || noFlagsSet,
wantBoundImp: *dumpBoundImport || noFlagsSet,
wantIAT: *dumpIAT || noFlagsSet,
wantDelayImp: *dumpDelayedImport || noFlagsSet,
wantCLR: *dumpCLR || noFlagsSet,
}
// Start as many workers you want, default to cpu count -1.
numWorkers := runtime.GOMAXPROCS(runtime.NumCPU() - 1)
for w := 1; w <= numWorkers; w++ {
go loopFilesWorker(cfg)
}
if !isDirectory(filePath) {
// Input path in a single file.
parsePE(filePath, cfg)
} else {
// Input path in a directory.
LoopDirsFiles(filePath)
wg.Wait()
}
case "version":
fmt.Println("You are using version 1.6.0")
default:
showHelp()
}
}
func showHelp() {
fmt.Print(
`
╔═╗╔═╗ ┌─┐┌─┐┬─┐┌─┐┌─┐┬─┐
╠═╝║╣ ├─┘├─┤├┬┘└─┐├┤ ├┬┘
╩ ╚═╝ ┴ ┴ ┴┴└─└─┘└─┘┴└─
A PE-Parser built for speed and malware-analysis in mind.
Brought to you by Saferwall (c) 2018 MIT
Usage: pedumper <command> [options]
Commands:
dump [flags] <file-or-directory> Parse and dump PE file information
version Show version information
Run 'pedumper dump -help' for dump flags.
`)
os.Exit(1)
}
================================================
FILE: cmd/size.go
================================================
package main
import (
"fmt"
"strconv"
"strings"
)
// See: http://en.wikipedia.org/wiki/Binary_prefix
const (
// Decimal
KB = 1000
MB = 1000 * KB
GB = 1000 * MB
TB = 1000 * GB
PB = 1000 * TB
// Binary
KiB = 1024
MiB = 1024 * KiB
GiB = 1024 * MiB
TiB = 1024 * GiB
PiB = 1024 * TiB
)
type unitMap map[byte]int64
var (
decimalMap = unitMap{'k': KB, 'm': MB, 'g': GB, 't': TB, 'p': PB}
binaryMap = unitMap{'k': KiB, 'm': MiB, 'g': GiB, 't': TiB, 'p': PiB}
)
var (
decimapAbbrs = []string{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}
binaryAbbrs = []string{"B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"}
)
func getSizeAndUnit(size float64, base float64, _map []string) (float64, string) {
i := 0
unitsLimit := len(_map) - 1
for size >= base && i < unitsLimit {
size = size / base
i++
}
return size, _map[i]
}
// CustomSize returns a human-readable approximation of a size
// using custom format.
func CustomSize(format string, size float64, base float64, _map []string) string {
size, unit := getSizeAndUnit(size, base, _map)
return fmt.Sprintf(format, size, unit)
}
// HumanSizeWithPrecision allows the size to be in any precision,
// instead of 4 digit precision used in units.HumanSize.
func HumanSizeWithPrecision(size float64, precision int) string {
size, unit := getSizeAndUnit(size, 1000.0, decimapAbbrs)
return fmt.Sprintf("%.*g%s", precision, size, unit)
}
// HumanSize returns a human-readable approximation of a size
// capped at 4 valid numbers (eg. "2.746 MB", "796 KB").
func HumanSize(size float64) string {
return HumanSizeWithPrecision(size, 4)
}
// BytesSize returns a human-readable size in bytes, kibibytes,
// mebibytes, gibibytes, or tebibytes (eg. "44kiB", "17MiB").
func BytesSize(size float64) string {
return CustomSize("%.4g%s", size, 1024.0, binaryAbbrs)
}
// FromHumanSize returns an integer from a human-readable specification of a
// size using SI standard (eg. "44kB", "17MB").
func FromHumanSize(size string) (int64, error) {
return parseSize(size, decimalMap)
}
// RAMInBytes parses a human-readable string representing an amount of RAM
// in bytes, kibibytes, mebibytes, gibibytes, or tebibytes and
// returns the number of bytes, or -1 if the string is unparseable.
// Units are case-insensitive, and the 'b' suffix is optional.
func RAMInBytes(size string) (int64, error) {
return parseSize(size, binaryMap)
}
// Parses the human-readable size string into the amount it represents.
func parseSize(sizeStr string, uMap unitMap) (int64, error) {
// TODO: rewrite to use strings.Cut if there's a space
// once Go < 1.18 is deprecated.
sep := strings.LastIndexAny(sizeStr, "01234567890. ")
if sep == -1 {
// There should be at least a digit.
return -1, fmt.Errorf("invalid size: '%s'", sizeStr)
}
var num, sfx string
if sizeStr[sep] != ' ' {
num = sizeStr[:sep+1]
sfx = sizeStr[sep+1:]
} else {
// Omit the space separator.
num = sizeStr[:sep]
sfx = sizeStr[sep+1:]
}
size, err := strconv.ParseFloat(num, 64)
if err != nil {
return -1, err
}
// Backward compatibility: reject negative sizes.
if size < 0 {
return -1, fmt.Errorf("invalid size: '%s'", sizeStr)
}
if len(sfx) == 0 {
return int64(size), nil
}
// Process the suffix.
if len(sfx) > 3 { // Too long.
goto badSuffix
}
sfx = strings.ToLower(sfx)
// Trivial case: b suffix.
if sfx[0] == 'b' {
if len(sfx) > 1 { // no extra characters allowed after b.
goto badSuffix
}
return int64(size), nil
}
// A suffix from the map.
if mul, ok := uMap[sfx[0]]; ok {
size *= float64(mul)
} else {
goto badSuffix
}
// The suffix may have extra "b" or "ib" (e.g. KiB or MB).
switch {
case len(sfx) == 2 && sfx[1] != 'b':
goto badSuffix
case len(sfx) == 3 && sfx[1:] != "ib":
goto badSuffix
}
return int64(size), nil
badSuffix:
return -1, fmt.Errorf("invalid suffix: '%s'", sfx)
}
================================================
FILE: cmd/size_test.go
================================================
package main
import (
"fmt"
"reflect"
"runtime"
"strings"
"testing"
)
func ExampleBytesSize() {
fmt.Println(BytesSize(1024))
fmt.Println(BytesSize(1024 * 1024))
fmt.Println(BytesSize(1048576))
fmt.Println(BytesSize(2 * MiB))
fmt.Println(BytesSize(3.42 * GiB))
fmt.Println(BytesSize(5.372 * TiB))
fmt.Println(BytesSize(2.22 * PiB))
}
func ExampleHumanSize() {
fmt.Println(HumanSize(1000))
fmt.Println(HumanSize(1024))
fmt.Println(HumanSize(1000000))
fmt.Println(HumanSize(1048576))
fmt.Println(HumanSize(2 * MB))
fmt.Println(HumanSize(float64(3.42 * GB)))
fmt.Println(HumanSize(float64(5.372 * TB)))
fmt.Println(HumanSize(float64(2.22 * PB)))
}
func ExampleFromHumanSize() {
fmt.Println(FromHumanSize("32"))
fmt.Println(FromHumanSize("32b"))
fmt.Println(FromHumanSize("32B"))
fmt.Println(FromHumanSize("32k"))
fmt.Println(FromHumanSize("32K"))
fmt.Println(FromHumanSize("32kb"))
fmt.Println(FromHumanSize("32Kb"))
fmt.Println(FromHumanSize("32Mb"))
fmt.Println(FromHumanSize("32Gb"))
fmt.Println(FromHumanSize("32Tb"))
fmt.Println(FromHumanSize("32Pb"))
}
func ExampleRAMInBytes() {
fmt.Println(RAMInBytes("32"))
fmt.Println(RAMInBytes("32b"))
fmt.Println(RAMInBytes("32B"))
fmt.Println(RAMInBytes("32k"))
fmt.Println(RAMInBytes("32K"))
fmt.Println(RAMInBytes("32kb"))
fmt.Println(RAMInBytes("32Kb"))
fmt.Println(RAMInBytes("32Mb"))
fmt.Println(RAMInBytes("32Gb"))
fmt.Println(RAMInBytes("32Tb"))
fmt.Println(RAMInBytes("32Pb"))
fmt.Println(RAMInBytes("32PB"))
fmt.Println(RAMInBytes("32P"))
}
func TestBytesSize(t *testing.T) {
assertEquals(t, "1KiB", BytesSize(1024))
assertEquals(t, "1MiB", BytesSize(1024*1024))
assertEquals(t, "1MiB", BytesSize(1048576))
assertEquals(t, "2MiB", BytesSize(2*MiB))
assertEquals(t, "3.42GiB", BytesSize(3.42*GiB))
assertEquals(t, "5.372TiB", BytesSize(5.372*TiB))
assertEquals(t, "2.22PiB", BytesSize(2.22*PiB))
assertEquals(t, "1.049e+06YiB", BytesSize(KiB*KiB*KiB*KiB*KiB*PiB))
}
func TestHumanSize(t *testing.T) {
assertEquals(t, "1kB", HumanSize(1000))
assertEquals(t, "1.024kB", HumanSize(1024))
assertEquals(t, "1MB", HumanSize(1000000))
assertEquals(t, "1.049MB", HumanSize(1048576))
assertEquals(t, "2MB", HumanSize(2*MB))
assertEquals(t, "3.42GB", HumanSize(float64(3.42*GB)))
assertEquals(t, "5.372TB", HumanSize(float64(5.372*TB)))
assertEquals(t, "2.22PB", HumanSize(float64(2.22*PB)))
assertEquals(t, "1e+04YB", HumanSize(float64(10000000000000*PB)))
}
func TestFromHumanSize(t *testing.T) {
assertSuccessEquals(t, 0, FromHumanSize, "0")
assertSuccessEquals(t, 0, FromHumanSize, "0b")
assertSuccessEquals(t, 0, FromHumanSize, "0B")
assertSuccessEquals(t, 0, FromHumanSize, "0 B")
assertSuccessEquals(t, 32, FromHumanSize, "32")
assertSuccessEquals(t, 32, FromHumanSize, "32b")
assertSuccessEquals(t, 32, FromHumanSize, "32B")
assertSuccessEquals(t, 32*KB, FromHumanSize, "32k")
assertSuccessEquals(t, 32*KB, FromHumanSize, "32K")
assertSuccessEquals(t, 32*KB, FromHumanSize, "32kb")
assertSuccessEquals(t, 32*KB, FromHumanSize, "32Kb")
assertSuccessEquals(t, 32*MB, FromHumanSize, "32Mb")
assertSuccessEquals(t, 32*GB, FromHumanSize, "32Gb")
assertSuccessEquals(t, 32*TB, FromHumanSize, "32Tb")
assertSuccessEquals(t, 32*PB, FromHumanSize, "32Pb")
assertSuccessEquals(t, 32.5*KB, FromHumanSize, "32.5kB")
assertSuccessEquals(t, 32.5*KB, FromHumanSize, "32.5 kB")
assertSuccessEquals(t, 32, FromHumanSize, "32.5 B")
assertSuccessEquals(t, 300, FromHumanSize, "0.3 K")
assertSuccessEquals(t, 300, FromHumanSize, ".3kB")
assertSuccessEquals(t, 0, FromHumanSize, "0.")
assertSuccessEquals(t, 0, FromHumanSize, "0. ")
assertSuccessEquals(t, 0, FromHumanSize, "0.b")
assertSuccessEquals(t, 0, FromHumanSize, "0.B")
assertSuccessEquals(t, 0, FromHumanSize, "-0")
assertSuccessEquals(t, 0, FromHumanSize, "-0b")
assertSuccessEquals(t, 0, FromHumanSize, "-0B")
assertSuccessEquals(t, 0, FromHumanSize, "-0 b")
assertSuccessEquals(t, 0, FromHumanSize, "-0 B")
assertSuccessEquals(t, 32, FromHumanSize, "32.")
assertSuccessEquals(t, 32, FromHumanSize, "32.b")
assertSuccessEquals(t, 32, FromHumanSize, "32.B")
assertSuccessEquals(t, 32, FromHumanSize, "32. b")
assertSuccessEquals(t, 32, FromHumanSize, "32. B")
// We do not tolerate extra leading or trailing spaces
// (except for a space after the number and a missing suffix).
assertSuccessEquals(t, 0, FromHumanSize, "0 ")
assertError(t, FromHumanSize, " 0")
assertError(t, FromHumanSize, " 0b")
assertError(t, FromHumanSize, " 0B")
assertError(t, FromHumanSize, " 0 B")
assertError(t, FromHumanSize, "0b ")
assertError(t, FromHumanSize, "0B ")
assertError(t, FromHumanSize, "0 B ")
assertError(t, FromHumanSize, "")
assertError(t, FromHumanSize, "hello")
assertError(t, FromHumanSize, ".")
assertError(t, FromHumanSize, ". ")
assertError(t, FromHumanSize, " ")
assertError(t, FromHumanSize, " ")
assertError(t, FromHumanSize, " .")
assertError(t, FromHumanSize, " . ")
assertError(t, FromHumanSize, "-32")
assertError(t, FromHumanSize, "-32b")
assertError(t, FromHumanSize, "-32B")
assertError(t, FromHumanSize, "-32 b")
assertError(t, FromHumanSize, "-32 B")
assertError(t, FromHumanSize, "32b.")
assertError(t, FromHumanSize, "32B.")
assertError(t, FromHumanSize, "32 b.")
assertError(t, FromHumanSize, "32 B.")
assertError(t, FromHumanSize, "32 bb")
assertError(t, FromHumanSize, "32 BB")
assertError(t, FromHumanSize, "32 b b")
assertError(t, FromHumanSize, "32 B B")
assertError(t, FromHumanSize, "32 b")
assertError(t, FromHumanSize, "32 B")
assertError(t, FromHumanSize, " 32 ")
assertError(t, FromHumanSize, "32m b")
assertError(t, FromHumanSize, "32bm")
}
func TestRAMInBytes(t *testing.T) {
assertSuccessEquals(t, 32, RAMInBytes, "32")
assertSuccessEquals(t, 32, RAMInBytes, "32b")
assertSuccessEquals(t, 32, RAMInBytes, "32B")
assertSuccessEquals(t, 32*KiB, RAMInBytes, "32k")
assertSuccessEquals(t, 32*KiB, RAMInBytes, "32K")
assertSuccessEquals(t, 32*KiB, RAMInBytes, "32kb")
assertSuccessEquals(t, 32*KiB, RAMInBytes, "32Kb")
assertSuccessEquals(t, 32*KiB, RAMInBytes, "32Kib")
assertSuccessEquals(t, 32*KiB, RAMInBytes, "32KIB")
assertSuccessEquals(t, 32*MiB, RAMInBytes, "32Mb")
assertSuccessEquals(t, 32*GiB, RAMInBytes, "32Gb")
assertSuccessEquals(t, 32*TiB, RAMInBytes, "32Tb")
assertSuccessEquals(t, 32*PiB, RAMInBytes, "32Pb")
assertSuccessEquals(t, 32*PiB, RAMInBytes, "32PB")
assertSuccessEquals(t, 32*PiB, RAMInBytes, "32P")
assertSuccessEquals(t, 32, RAMInBytes, "32.3")
tmp := 32.3 * MiB
assertSuccessEquals(t, int64(tmp), RAMInBytes, "32.3 mb")
tmp = 0.3 * MiB
assertSuccessEquals(t, int64(tmp), RAMInBytes, "0.3MB")
assertError(t, RAMInBytes, "")
assertError(t, RAMInBytes, "hello")
assertError(t, RAMInBytes, "-32")
assertError(t, RAMInBytes, " 32 ")
assertError(t, RAMInBytes, "32m b")
assertError(t, RAMInBytes, "32bm")
}
func BenchmarkParseSize(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, s := range []string{
"", "32", "32b", "32 B", "32k", "32.5 K", "32kb", "32 Kb",
"32.8Mb", "32.9Gb", "32.777Tb", "32Pb", "0.3Mb", "-1",
} {
FromHumanSize(s)
RAMInBytes(s)
}
}
}
func assertEquals(t *testing.T, expected, actual interface{}) {
t.Helper()
if expected != actual {
t.Errorf("Expected '%v' but got '%v'", expected, actual)
}
}
// func that maps to the parse function signatures as testing abstraction
type parseFn func(string) (int64, error)
// Define 'String()' for pretty-print
func (fn parseFn) String() string {
fnName := runtime.FuncForPC(reflect.ValueOf(fn).Pointer()).Name()
return fnName[strings.LastIndex(fnName, ".")+1:]
}
func assertSuccessEquals(t *testing.T, expected int64, fn parseFn, arg string) {
t.Helper()
res, err := fn(arg)
if err != nil || res != expected {
t.Errorf("%s(\"%s\") -> expected '%d' but got '%d' with error '%v'", fn, arg, expected, res, err)
}
}
func assertError(t *testing.T, fn parseFn, arg string) {
t.Helper()
res, err := fn(arg)
if err == nil && res != -1 {
t.Errorf("%s(\"%s\") -> expected error but got '%d'", fn, arg, res)
}
}
================================================
FILE: debug.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.
package pe
import (
"encoding/binary"
"errors"
"fmt"
)
// The following values are defined for the Type field of the debug directory entry:
const (
// An unknown value that is ignored by all tools.
ImageDebugTypeUnknown = 0
// The COFF debug information (line numbers, symbol table, and string table).
// This type of debug information is also pointed to by fields in the file headers.
ImageDebugTypeCOFF = 1
// The Visual C++ debug information.
ImageDebugTypeCodeView = 2
// The frame pointer omission (FPO) information. This information tells the
// debugger how to interpret nonstandard stack frames, which use the EBP
// register for a purpose other than as a frame pointer.
ImageDebugTypeFPO = 3
// The location of DBG file.
ImageDebugTypeMisc = 4
// A copy of .pdata section.
ImageDebugTypeException = 5
// Reserved.
ImageDebugTypeFixup = 6
// The mapping from an RVA in image to an RVA in source image.
ImageDebugTypeOMAPToSrc = 7
// The mapping from an RVA in source image to an RVA in image.
ImageDebugTypeOMAPFromSrc = 8
// Reserved for Borland.
ImageDebugTypeBorland = 9
// Reserved.
ImageDebugTypeReserved = 10
// Reserved.
ImageDebugTypeCLSID = 11
// Visual C++ features (/GS counts /sdl counts and guardN counts).
ImageDebugTypeVCFeature = 12
// Pogo aka PGO aka Profile Guided Optimization.
ImageDebugTypePOGO = 13
// Incremental Link Time Code Generation (iLTCG).
ImageDebugTypeILTCG = 14
// Intel MPX.
ImageDebugTypeMPX = 15
// PE determinism or reproducibility.
ImageDebugTypeRepro = 16
// Extended DLL characteristics bits.
ImageDebugTypeExDllCharacteristics = 20
)
const (
// CVSignatureRSDS represents the CodeView signature 'SDSR'.
CVSignatureRSDS = 0x53445352
// CVSignatureNB10 represents the CodeView signature 'NB10'.
CVSignatureNB10 = 0x3031424e
)
const (
// FrameFPO indicates a frame of type FPO.
FrameFPO = 0x0
// FrameTrap indicates a frame of type Trap.
FrameTrap = 0x1
// FrameTSS indicates a frame of type TSS.
FrameTSS = 0x2
// FrameNonFPO indicates a frame of type Non-FPO.
FrameNonFPO = 0x3
)
// DllCharacteristicsExType represents a DLL Characteristics type.
type DllCharacteristicsExType uint32
const (
// ImageDllCharacteristicsExCETCompat indicates that the image is CET
// compatible.
ImageDllCharacteristicsExCETCompat = 0x0001
)
const (
// POGOTypePGU represents a signature for an undocumented PGO sub type.
POGOTypePGU = 0x50475500
// POGOTypePGI represents a signature for an undocumented PGO sub type.
POGOTypePGI = 0x50474900
// POGOTypePGO represents a signature for an undocumented PGO sub type.
POGOTypePGO = 0x50474F00
// POGOTypeLTCG represents a signature for an undocumented PGO sub type.
POGOTypeLTCG = 0x4c544347
)
// ImageDebugDirectoryType represents the type of a debug directory.
type ImageDebugDirectoryType uint32
// ImageDebugDirectory represents the IMAGE_DEBUG_DIRECTORY structure.
// This directory indicates what form of debug information is present
// and where it is. This directory consists of an array of debug directory
// entries whose location and size are indicated in the image optional header.
type ImageDebugDirectory struct {
// Reserved, must be 0.
Characteristics uint32 `json:"characteristics"`
// The time and date that the debug data was created.
TimeDateStamp uint32 `json:"time_date_stamp"`
// The major version number of the debug data format.
MajorVersion uint16 `json:"major_version"`
// The minor version number of the debug data format.
MinorVersion uint16 `json:"minor_version"`
// The format of debugging information. This field enables support of
// multiple debuggers.
Type ImageDebugDirectoryType `json:"type"`
// The size of the debug data (not including the debug directory itself).
SizeOfData uint32 `json:"size_of_data"`
//The address of the debug data when loaded, relative to the image base.
AddressOfRawData uint32 `json:"address_of_raw_data"`
// The file pointer to the debug data.
PointerToRawData uint32 `json:"pointer_to_raw_data"`
}
// DebugEntry wraps ImageDebugDirectory to include debug directory type.
type DebugEntry struct {
// Points to the image debug entry structure.
Struct ImageDebugDirectory `json:"struct"`
// Holds specific information about the debug type entry.
Info interface{} `json:"info"`
// Type of the debug entry.
Type string `json:"type"`
}
// GUID is a 128-bit value consisting of one group of 8 hexadecimal digits,
// followed by three groups of 4 hexadecimal digits each, followed by one
// group of 12 hexadecimal digits.
type GUID struct {
Data1 uint32
Data2 uint16
Data3 uint16
Data4 [8]byte
}
// CVSignature represents a CodeView signature.
type CVSignature uint32
// CVInfoPDB70 represents the the CodeView data block of a PDB 7.0 file.
type CVInfoPDB70 struct {
// CodeView signature, equal to `RSDS`.
CVSignature CVSignature `json:"cv_signature"`
// A unique identifier, which changes with every rebuild of the executable and PDB file.
Signature GUID `json:"signature"`
// Ever-incrementing value, which is initially set to 1 and incremented every
// time when a part of the PDB file is updated without rewriting the whole file.
Age uint32 `json:"age"`
// Null-terminated name of the PDB file. It can also contain full or partial
// path to the file.
PDBFileName string `json:"pdb_file_name"`
}
// CVHeader represents the the CodeView header struct to the PDB 2.0 file.
type CVHeader struct {
// CodeView signature, equal to `NB10`.
Signature CVSignature `json:"signature"`
// CodeView offset. Set to 0, because debug information is stored in a
// separate file.
Offset uint32 `json:"offset"`
}
// CVInfoPDB20 represents the the CodeView data block of a PDB 2.0 file.
type CVInfoPDB20 struct {
// Points to the CodeView header structure.
CVHeader CVHeader `json:"cv_header"`
// The time when debug information was created (in seconds since 01.01.1970).
Signature uint32 `json:"signature"`
// Ever-incrementing value, which is initially set to 1 and incremented every
// time when a part of the PDB file is updated without rewriting the whole file.
Age uint32 `json:"age"`
// Null-terminated name of the PDB file. It can also contain full or partial
// path to the file.
PDBFileName string `json:"pdb_file_name"`
}
// FPOFrameType represents the type of a FPO frame.
type FPOFrameType uint8
// FPOData represents the stack frame layout for a function on an x86 computer when
// frame pointer omission (FPO) optimization is used. The structure is used to locate
// the base of the call frame.
type FPOData struct {
// The offset of the first byte of the function code.
OffsetStart uint32 `json:"offset_start"`
// The number of bytes in the function.
ProcSize uint32 `json:"proc_size"`
// The number of local variables.
NumLocals uint32 `json:"num_locals"`
// The size of the parameters, in DWORDs.
ParamsSize uint16 `json:"params_size"`
// The number of bytes in the function prolog code.
PrologLength uint8 `json:"prolog_length"`
// The number of registers saved.
SavedRegsCount uint8 `json:"saved_regs_count"`
// A variable that indicates whether the function uses structured exception handling.
HasSEH uint8 `json:"has_seh"`
// A variable that indicates whether the EBP register has been allocated.
UseBP uint8 `json:"use_bp"`
// Reserved for future use.
Reserved uint8 `json:"reserved"`
// A variable that indicates the frame type.
FrameType FPOFrameType `json:"frame_type"`
}
// ImagePGOItem represents the _IMAGE_POGO_INFO structure.
type ImagePGOItem struct {
RVA uint32 `json:"rva"`
Size uint32 `json:"size"`
Name string `json:"name"`
}
// POGOType represents a POGO type.
type POGOType uint32
// POGO structure contains information related to the Profile Guided Optimization.
// PGO is an approach to optimization where the compiler uses profile information
// to make better optimization decisions for the program.
type POGO struct {
// Signature represents the PGO sub type.
Signature POGOType `json:"signature"`
Entries []ImagePGOItem `json:"entries"`
}
type VCFeature struct {
PreVC11 uint32 `json:"pre_vc11"`
CCpp uint32 `json:"C/C++"`
Gs uint32 `json:"/GS"`
Sdl uint32 `json:"/sdl"`
GuardN uint32 `json:"guardN"`
}
type REPRO struct {
Size uint32 `json:"size"`
Hash []byte `json:"hash"`
}
// ImageDebugMisc represents the IMAGE_DEBUG_MISC structure.
type ImageDebugMisc struct {
// The type of data carried in the `Data` field.
DataType uint32 `json:"data_type"`
// The length of this structure in bytes, including the entire Data field
// and its NUL terminator (rounded to four byte multiple.)
Length uint32 `json:"length"`
// The encoding of the Data field. True if data is unicode string.
Unicode bool `json:"unicode"`
// Reserved.
Reserved [3]byte `json:"reserved"`
// Actual data.
Data string `json:"data"`
}
// Image files contain an optional debug directory that indicates what form of
// debug information is present and where it is. This directory consists of an
// array of debug directory entries whose location and size are indicated in the
// image optional header. The debug directory can be in a discardable .debug
// section (if one exists), or it can be included in any other section in the
// image file, or not be in a section at all.
func (pe *File) parseDebugDirectory(rva, size uint32) error {
debugEntry := DebugEntry{}
debugDir := ImageDebugDirectory{}
errorMsg := fmt.Sprintf("Invalid debug information. Can't read data at RVA: 0x%x", rva)
debugDirSize := uint32(binary.Size(debugDir))
debugDirsCount := size / debugDirSize
for i := uint32(0); i < debugDirsCount; i++ {
offset := pe.GetOffsetFromRva(rva + debugDirSize*i)
err := pe.structUnpack(&debugDir, offset, debugDirSize)
if err != nil {
return errors.New(errorMsg)
}
switch debugDir.Type {
case ImageDebugTypeCodeView:
debugSignature, err := pe.ReadUint32(debugDir.PointerToRawData)
if err != nil {
continue
}
if debugSignature == CVSignatureRSDS {
// PDB 7.0
pdb := CVInfoPDB70{CVSignature: CVSignatureRSDS}
// Extract the GUID.
offset := debugDir.PointerToRawData + 4
guidSize := uint32(binary.Size(pdb.Signature))
err = pe.structUnpack(&pdb.Signature, offset, guidSize)
if err != nil {
continue
}
// Extract the age.
offset += guidSize
pdb.Age, err = pe.ReadUint32(offset)
if err != nil {
continue
}
offset += 4
// PDB file name.
pdbFilenameSize := debugDir.SizeOfData - 24 - 1
// pdbFileName_size can be negative here, as seen in the malware
// sample with MD5 hash: 7c297600870d026c014d42596bb9b5fd
// Checking for positive size here to ensure proper parsing.
if pdbFilenameSize > 0 {
pdbFilename := make([]byte, pdbFilenameSize)
err = pe.structUnpack(&pdbFilename, offset, pdbFilenameSize)
if err != nil {
continue
}
pdb.PDBFileName = string(pdbFilename)
}
// Include these extra information.
debugEntry.Info = pdb
} else if debugSignature == CVSignatureNB10 {
// PDB 2.0.
cvHeader := CVHeader{}
offset := debugDir.PointerToRawData
err = pe.structUnpack(&cvHeader, offset, size)
if err != nil {
continue
}
pdb := CVInfoPDB20{CVHeader: cvHeader}
// Extract the signature.
pdb.Signature, err = pe.ReadUint32(offset + 8)
if err != nil {
continue
}
// Extract the age.
pdb.Age, err = pe.ReadUint32(offset + 12)
if err != nil {
continue
}
offset += 16
pdbFilenameSize := debugDir.SizeOfData - 16 - 1
if pdbFilenameSize > 0 {
pdbFilename := make([]byte, pdbFilenameSize)
err = pe.structUnpack(&pdbFilename, offset, pdbFilenameSize)
if err != nil {
continue
}
pdb.PDBFileName = string(pdbFilename)
}
// Include these extra information.
debugEntry.Info = pdb
}
case ImageDebugTypePOGO:
pogoSignature, err := pe.ReadUint32(debugDir.PointerToRawData)
if err != nil {
continue
}
pogo := POGO{}
switch pogoSignature {
case 0x0, POGOTypePGU, POGOTypePGI, POGOTypePGO, POGOTypeLTCG:
// TODO: Some files like 00da1a2a9d9ebf447508bf6550f05f466f8eabb4ed6c4f2a524c0769b2d75bc1
// have a POGO signature of 0x0. To be reverse engineered.
pogo.Signature = POGOType(pogoSignature)
offset = debugDir.PointerToRawData + 4
c := uint32(0)
for c < debugDir.SizeOfData-4 {
pogoEntry := ImagePGOItem{}
pogoEntry.RVA, err = pe.ReadUint32(offset)
if err != nil {
break
}
offset += 4
pogoEntry.Size, err = pe.ReadUint32(offset)
if err != nil {
break
}
offset += 4
pogoEntry.Name = string(pe.GetStringFromData(0, pe.data[offset:offset+64]))
pogo.Entries = append(pogo.Entries, pogoEntry)
offset += uint32(len(pogoEntry.Name))
// Make sure offset is aligned to 4 bytes.
padding := 4 - (offset % 4)
c += 4 + 4 + uint32(len(pogoEntry.Name)) + padding
offset += padding
}
debugEntry.Info = pogo
}
case ImageDebugTypeVCFeature:
vcf := VCFeature{}
size := uint32(binary.Size(vcf))
err := pe.structUnpack(&vcf, debugDir.PointerToRawData, size)
if err != nil {
continue
}
debugEntry.Info = vcf
case ImageDebugTypeRepro:
repro := REPRO{}
offset := debugDir.PointerToRawData
// Extract the size.
repro.Size, err = pe.ReadUint32(offset)
if err != nil {
continue
}
// Extract the hash.
repro.Hash, err = pe.ReadBytesAtOffset(offset+4, repro.Size)
if err != nil {
continue
}
debugEntry.Info = repro
case ImageDebugTypeFPO:
offset := debugDir.PointerToRawData
size := uint32(16)
fpoEntries := []FPOData{}
c := uint32(0)
for c < debugDir.SizeOfData {
fpo := FPOData{}
fpo.OffsetStart, err = pe.ReadUint32(offset)
if err != nil {
break
}
fpo.ProcSize, err = pe.ReadUint32(offset + 4)
if err != nil {
break
}
fpo.NumLocals, err = pe.ReadUint32(offset + 8)
if err != nil {
break
}
fpo.ParamsSize, err = pe.ReadUint16(offset + 12)
if err != nil {
break
}
fpo.PrologLength, err = pe.ReadUint8(offset + 14)
if err != nil {
break
}
attributes, err := pe.ReadUint16(offset + 15)
if err != nil {
break
}
//
// UChar cbRegs :3; /* # regs saved */
// UChar fHasSEH:1; /* Structured Exception Handling */
// UChar fUseBP :1; /* EBP has been used */
// UChar reserved:1;
// UChar cbFrame:2; /* frame type */
//
// The lowest 3 bits
fpo.SavedRegsCount = uint8(attributes & 0x7)
// The next bit.
fpo.HasSEH = uint8(attributes & 0x8 >> 3)
// The next bit.
fpo.UseBP = uint8(attributes & 0x10 >> 4)
// The next bit.
fpo.Reserved = uint8(attributes & 0x20 >> 5)
// The next 2 bits.
fpo.FrameType = FPOFrameType(attributes & 0xC0 >> 6)
fpoEntries = append(fpoEntries, fpo)
c += size
offset += 16
}
debugEntry.Info = fpoEntries
case ImageDebugTypeExDllCharacteristics:
exDllChar, err := pe.ReadUint32(debugDir.PointerToRawData)
if err != nil {
continue
}
debugEntry.Info = DllCharacteristicsExType(exDllChar)
}
debugEntry.Struct = debugDir
debugEntry.Type = debugDir.Type.String()
pe.Debugs = append(pe.Debugs, debugEntry)
}
if len(pe.Debugs) > 0 {
pe.HasDebug = true
}
return nil
}
// SectionAttributeDescription maps a section attribute to a friendly name.
func SectionAttributeDescription(section string) string {
sectionNameMap := map[string]string{
".00cfg": "CFG Check Functions Pointers",
".bss$00": "Uninit.data in phaseN of Pri7",
".bss$dk00": "PGI: Uninit.data may be not const",
".bss$dk01": "PGI: Uninit.data may be not const",
".bss$pr00": "PGI: Uninit.data only for read",
".bss$pr03": "PGI: Uninit.data only for read",
".bss$zz": "PGO: Dead uninit.data",
".CRT$XCA": "First C++ Initializer",
".CRT$XCZ": "Last C++ Initializer",
".xdata$x": "EH data",
".gfids$y": "CFG Functions table",
".CRT$XCAA": "Startup C++ Initializer",
".CRT$XCC": "Global initializer: init_seg(compiler)",
".CRT$XCL": "Global initializer: init_seg(lib)",
".CRT$XCU": "Global initializer: init_seg(user)",
".CRT$XDA": "First Dynamic TLS Initializer",
".CRT$XDZ": "Last Dynamic TLS Initializer",
".CRT$XIA": "First C Initializer",
".CRT$XIAA": "Startup C Initializer",
".CRT$XIAB": "PGO C Initializer",
".CRT$XIAC": "Post-PGO C Initializer",
".CRT$XIC": "CRT C Initializers",
".CRT$XIYA": "VCCorLib Threading Model Initializer",
".CRT$XIYAA": "XAML Designer Threading Model Override Initializer",
".CRT$XIYB": "VCCorLib Main Initializer",
".CRT$XIZ": "Last C Initializer",
".CRT$XLA": "First Loader TLS Callback",
".CRT$XLC": "CRT TLS Constructor",
".CRT$XLD": "CRT TLS Terminator",
".CRT$XLZ": "Last Loader TLS Callback",
".CRT$XPA": "First Pre-Terminator",
".CRT$XPB": "CRT ConcRT Pre-Terminator",
".CRT$XPX": "CRT Pre-Terminators",
".CRT$XPXA": "CRT stdio Pre-Terminator",
".CRT$XPZ": "Last Pre-Terminator",
".CRT$XTA": "First Terminator",
".CRT$XTZ": "Last Terminator",
".CRTMA$XCA": "First Managed C++ Initializer",
".CRTMA$XCZ": "Last Managed C++ Initializer",
".CRTVT$XCA": "First Managed VTable Initializer",
".CRTVT$XCZ": "Last Managed VTable Initializer",
".data$00": "Init.data in phaseN of Pri7",
".data$dk00": "PGI: Init.data may be not const",
".data$dk00$brc": "PGI: Init.data may be not const",
".data$pr00": "PGI: Init.data only for read",
".data$r": "RTTI Type Descriptors",
".data$zz": "PGO: Dead init.data",
".data$zz$brc": "PGO: Dead init.data",
".didat$2": "Delay Import Descriptors",
".didat$3": "Delay Import Final NULL Entry",
".didat$4": "Delay Import INT",
".didat$5": "Delay Import IAT",
".didat$6": "Delay Import Symbol Names",
".didat$7": "Delay Import Bound IAT",
".edata": "Export Table",
".gehcont": "CFG EHCont Table",
".gfids": "CFG Functions Table",
".giats": "CFG IAT Table",
".idata$2": "Import Descriptors",
".idata$3": "Import Final NULL Entry",
".idata$4": "Import Names Table",
".idata$5": "Import Addresses Table",
".idata$6": "Import Symbol and DLL Names",
".pdata": "Procedure data",
".rdata$00": "Readonly data in phaseN of Pri7",
".rdata$00$brc": "Readonly data in phaseN of Pri7",
".rdata$09": "Readonly data in phaseN of Pri7",
".rdata$brc": "BaseRelocation Clustering",
".rdata$r": "RTTI Data",
".rdata$sxdata": "Safe SEH",
".rdata$T": "TLS Header",
".rdata$zETW0": "ETW Metadata Header",
".rdata$zETW1": "ETW Events Metadata",
".rdata$zETW2": "ETW Providers Metadata",
".rdata$zETW9": "ETW Metadata Footer",
".rdata$zz": "PGO: Dead Readonly Data",
".rdata$zz$brc": "PGO: Dead Readonly Data",
".rdata$zzzdbg": "Debug directory data",
".rsrc$01": "Resources Header",
".rsrc$02": "Resources Data",
".rtc$IAA": "First RTC Initializer",
".rtc$IZZ": "Last RTC Initializer",
".rtc$TAA": "First RTC Terminator",
".rtc$TZZ": "Last RTC Terminator",
".text$di": "MSVC Dynamic Initializers",
".text$lp00kernel32.dll!20_pri7": "PGO: LoaderPhaseN warm-to-hot code",
".text$lp01kernel32.dll!20_pri7": "PGO: LoaderPhaseN warm-to-hot code",
".text$lp03kernel32.dll!30_clientonly": "PGO: LoaderPhaseN warm-to-hot code",
".text$lp04kernel32.dll!30_clientonly": "PGO: LoaderPhaseN warm-to-hot code",
".text$lp08kernel32.dll!40_serveronly": "PGO: LoaderPhaseN warm-to-hot code",
".text$lp09kernel32.dll!40_serveronly": "PGO: LoaderPhaseN warm-to-hot code",
".text$lp10kernel32.dll!40_serveronly": "PGO: LoaderPhaseN warm-to-hot code",
".text$mn": "Contains EP",
".text$mn$00": "CFG Dispatching",
".text$np": "PGO: __asm or disabled via pragma",
".text$x": "EH Filters",
".text$yd": "MSVC Destructors",
".text$zy": "PGO: Dead Code Blocks",
".text$zz": "PGO: Dead Whole Functions",
".xdata": "Unwind data",
}
if val, ok := sectionNameMap[section]; ok {
return val
}
return ""
}
// String returns a string interpretation of the FPO frame type.
func (ft FPOFrameType) String() string {
frameTypeMap := map[FPOFrameType]string{
FrameFPO: "FPO",
FrameTrap: "Trap",
FrameTSS: "TSS",
FrameNonFPO: "Non FPO",
}
v, ok := frameTypeMap[ft]
if ok {
return v
}
return "?"
}
// String returns the string representation of a GUID.
func (g GUID) String() string {
return fmt.Sprintf("{%06X-%04X-%04X-%04X-%X}", g.Data1, g.Data2, g.Data3, g.Data4[0:2], g.Data4[2:])
}
// String returns the string representation of a debug entry type.
func (t ImageDebugDirectoryType) String() string {
debugTypeMap := map[ImageDebugDirectoryType]string{
ImageDebugTypeUnknown: "Unknown",
ImageDebugTypeCOFF: "COFF",
ImageDebugTypeCodeView: "CodeView",
ImageDebugTypeFPO: "FPO",
ImageDebugTypeMisc: "Misc",
ImageDebugTypeException: "Exception",
ImageDebugTypeFixup: "Fixup",
ImageDebugTypeOMAPToSrc: "OMAP To Src",
ImageDebugTypeOMAPFromSrc: "OMAP From Src",
ImageDebugTypeBorland: "Borland",
ImageDebugTypeReserved: "Reserved",
ImageDebugTypeVCFeature: "VC Feature",
ImageDebugTypePOGO: "POGO",
ImageDebugTypeILTCG: "iLTCG",
ImageDebugTypeMPX: "MPX",
ImageDebugTypeRepro: "REPRO",
ImageDebugTypeExDllCharacteristics: "Ex.DLL Characteristics",
}
v, ok := debugTypeMap[t]
if ok {
return v
}
return "?"
}
// String returns a string interpretation of a POGO type.
func (p POGOType) String() string {
pogoTypeMap := map[POGOType]string{
POGOTypePGU: "PGU",
POGOTypePGI: "PGI",
POGOTypePGO: "PGO",
POGOTypeLTCG: "LTCG",
}
v, ok := pogoTypeMap[p]
if ok {
return v
}
return "?"
}
// String returns a string interpretation of a CodeView signature.
func (s CVSignature) String() string {
cvSignatureMap := map[CVSignature]string{
CVSignatureRSDS: "RSDS",
CVSignatureNB10: "NB10",
}
v, ok := cvSignatureMap[s]
if ok {
return v
}
return "?"
}
// String returns a string interpretation of Dll Characteristics Ex.
func (flag DllCharacteristicsExType) String() string {
dllCharacteristicsExTypeMap := map[DllCharacteristicsExType]string{
ImageDllCharacteristicsExCETCompat: "CET Compatible",
}
v, ok := dllCharacteristicsExTypeMap[flag]
if ok {
return v
}
return "?"
}
================================================
FILE: debug_test.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.
package pe
import (
"reflect"
"testing"
)
type TestDebugIn struct {
filepath string
index int // debug entry index
}
func TestDebugDirectoryCodeView(t *testing.T) {
type TestCodeView struct {
debugEntry DebugEntry
signature string
}
tests := []struct {
in TestDebugIn
out TestCodeView
}{
{
TestDebugIn{
index: 0,
filepath: getAbsoluteFilePath("test/kernel32.dll"),
},
TestCodeView{
debugEntry: DebugEntry{
Struct: ImageDebugDirectory{
Characteristics: 0x0,
TimeDateStamp: 0x38b369c4,
MajorVersion: 0x0,
MinorVersion: 0x0,
Type: 0x2,
SizeOfData: 0x25,
AddressOfRawData: 0x932f0,
PointerToRawData: 0x91cf0,
},
Info: CVInfoPDB70{
CVSignature: 0x53445352,
Signature: GUID{
Data1: 0xdbe09e71,
Data2: 0xb370,
Data3: 0x9cb7,
Data4: [8]byte{34, 197, 94, 85, 115, 250, 123, 225},
},
Age: 0x1,
PDBFileName: "kernel32.pdb",
},
Type: "CodeView",
},
signature: "RSDS",
},
},
{
TestDebugIn{
index: 0,
filepath: getAbsoluteFilePath("test/01008963d32f5cc17b64c31446386ee5b36a7eab6761df87a2989ba9394d8f3d"),
},
TestCodeView{
debugEntry: DebugEntry{
Struct: ImageDebugDirectory{
Characteristics: 0x0,
TimeDateStamp: 0x3b7d84d4,
MajorVersion: 0x0,
MinorVersion: 0x0,
Type: 0x2,
SizeOfData: 0x1d,
AddressOfRawData: 0x1cf4,
PointerToRawData: 0x10f4,
},
Info: CVInfoPDB20{
CVHeader: CVHeader{
Signature: 0x3031424e,
Offset: 0x0,
},
Signature: 0x3b7d84d4,
Age: 0x1,
PDBFileName: "routemon.pdb",
},
Type: "CodeView",
},
signature: "NB10",
},
},
}
for _, tt := range tests {
t.Run(tt.in.filepath, func(t *testing.T) {
ops := Options{Fast: true}
file, err := New(tt.in.filepath, &ops)
if err != nil {
t.Fatalf("New(%s) failed, reason: %v", tt.in.filepath, err)
}
err = file.Parse()
if err != nil {
t.Fatalf("Parse(%s) failed, reason: %v", tt.in.filepath, err)
}
var va, size uint32
if file.Is64 {
oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
dirEntry := oh64.DataDirectory[ImageDirectoryEntryDebug]
va = dirEntry.VirtualAddress
size = dirEntry.Size
} else {
oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
dirEntry := oh32.DataDirectory[ImageDirectoryEntryDebug]
va = dirEntry.VirtualAddress
size = dirEntry.Size
}
err = file.parseDebugDirectory(va, size)
if err != nil {
t.Fatalf("parseExportDirectory(%s) failed, reason: %v",
tt.in.filepath, err)
}
debugEntry := file.Debugs[tt.in.index]
if !reflect.DeepEqual(debugEntry, tt.out.debugEntry) {
t.Fatalf("debug entry assertion failed, got %v, want %v",
debugEntry, tt.out.debugEntry)
}
cvSignature := ""
switch debugEntry.Info.(type) {
case CVInfoPDB70:
cvSignature = debugEntry.Info.(CVInfoPDB70).CVSignature.String()
case CVInfoPDB20:
cvSignature = debugEntry.Info.(CVInfoPDB20).CVHeader.Signature.String()
}
if cvSignature != tt.out.signature {
t.Fatalf("debug CV signature assertion failed, got %v, want %v",
cvSignature, tt.out.signature)
}
})
}
}
func TestDebugDirectoryPOGO(t *testing.T) {
type TestPOGO struct {
imgDebugEntry ImageDebugDirectory
entriesCount int
debugType string
POGOItemIndex int
POGOItem ImagePGOItem
POGOSignature string
}
tests := []struct {
in TestDebugIn
out TestPOGO
}{
{
TestDebugIn{
index: 1,
filepath: getAbsoluteFilePath("test/kernel32.dll"),
},
TestPOGO{
imgDebugEntry: ImageDebugDirectory{
Characteristics: 0x0,
TimeDateStamp: 0x38b369c4,
MajorVersion: 0x0,
MinorVersion: 0x0,
Type: 0xd,
SizeOfData: 0x574,
AddressOfRawData: 0x93318,
PointerToRawData: 0x91d18,
},
debugType: "POGO",
entriesCount: 60,
POGOItemIndex: 0,
POGOItem: ImagePGOItem{
RVA: 0x1000,
Size: 0x280,
Name: ".text$lp00kernel32.dll!20_pri7",
},
POGOSignature: "PGU",
},
},
}
for _, tt := range tests {
t.Run(tt.in.filepath, func(t *testing.T) {
ops := Options{Fast: true}
file, err := New(tt.in.filepath, &ops)
if err != nil {
t.Fatalf("New(%s) failed, reason: %v", tt.in.filepath, err)
}
err = file.Parse()
if err != nil {
t.Fatalf("Parse(%s) failed, reason: %v", tt.in.filepath, err)
}
var va, size uint32
if file.Is64 {
oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
dirEntry := oh64.DataDirectory[ImageDirectoryEntryDebug]
va = dirEntry.VirtualAddress
size = dirEntry.Size
} else {
oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
dirEntry := oh32.DataDirectory[ImageDirectoryEntryDebug]
va = dirEntry.VirtualAddress
size = dirEntry.Size
}
err = file.parseDebugDirectory(va, size)
if err != nil {
t.Fatalf("parseExportDirectory(%s) failed, reason: %v", tt.in.filepath, err)
}
imgDebugEntry := file.Debugs[tt.in.index].Struct
if !reflect.DeepEqual(imgDebugEntry, tt.out.imgDebugEntry) {
t.Fatalf("debug entry assertion failed, got %v, want %v",
imgDebugEntry, tt.out.imgDebugEntry)
}
debugTypeString := file.Debugs[tt.in.index].Type
if debugTypeString != tt.out.debugType {
t.Fatalf("debug type assertion failed, got %v, want %v",
debugTypeString, tt.out.debugType)
}
pogo := file.Debugs[tt.in.index].Info.(POGO)
entriesCount := len(pogo.Entries)
if entriesCount != tt.out.entriesCount {
t.Fatalf("debug entry count failed, got %v, want %v",
entriesCount, tt.out.entriesCount)
}
pogoItem := pogo.Entries[tt.out.POGOItemIndex]
if !reflect.DeepEqual(pogoItem, tt.out.POGOItem) {
t.Fatalf("debug pogo entry assertion failed, got %v, want %v",
pogoItem, tt.out.POGOItemIndex)
}
pogoItemSignature := pogo.Signature.String()
if pogoItemSignature != tt.out.POGOSignature {
t.Fatalf("debug pogo signature string assertion failed, got %v, want %v",
pogoItemSignature, tt.out.POGOSignature)
}
})
}
}
func TestDebugDirectoryREPRO(t *testing.T) {
type TestREPRO struct {
debugType string
debugEntry DebugEntry
}
tests := []struct {
in TestDebugIn
out TestREPRO
}{
{
TestDebugIn{
index: 2,
filepath: getAbsoluteFilePath("test/kernel32.dll"),
},
TestREPRO{
debugEntry: DebugEntry{
Struct: ImageDebugDirectory{
Characteristics: 0x0,
TimeDateStamp: 0x38b369c4,
MajorVersion: 0x0,
MinorVersion: 0x0,
Type: 0x10,
SizeOfData: 0x24,
AddressOfRawData: 0x9388c,
PointerToRawData: 0x9228c,
},
Info: REPRO{
Size: 0x20,
Hash: []byte{113, 158, 224, 219, 112, 179, 183, 156, 34, 197, 94, 85, 115, 250, 123, 225, 130,
247, 187, 89, 220, 154, 207, 99, 80, 113, 179, 171, 196, 105, 179, 56},
},
Type: "REPRO",
},
},
},
}
for _, tt := range tests {
t.Run(tt.in.filepath, func(t *testing.T) {
ops := Options{Fast: true}
file, err := New(tt.in.filepath, &ops)
if err != nil {
t.Fatalf("New(%s) failed, reason: %v", tt.in.filepath, err)
}
err = file.Parse()
if err != nil {
t.Fatalf("Parse(%s) failed, reason: %v", tt.in.filepath, err)
}
var va, size uint32
if file.Is64 {
oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
dirEntry := oh64.DataDirectory[ImageDirectoryEntryDebug]
va = dirEntry.VirtualAddress
size = dirEntry.Size
} else {
oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
dirEntry := oh32.DataDirectory[ImageDirectoryEntryDebug]
va = dirEntry.VirtualAddress
size = dirEntry.Size
}
err = file.parseDebugDirectory(va, size)
if err != nil {
t.Fatalf("parseExportDirectory(%s) failed, reason: %v",
tt.in.filepath, err)
}
debugEntry := file.Debugs[tt.in.index]
if !reflect.DeepEqual(debugEntry, tt.out.debugEntry) {
t.Fatalf("debug entry assertion failed, got %v, want %v",
debugEntry, tt.out.debugEntry)
}
})
}
}
func TestDebugDirectoryExDLLCharacteristics(t *testing.T) {
type TestExDLLCharacteristics struct {
debugEntry DebugEntry
exDLLCharacteristics string
}
tests := []struct {
in TestDebugIn
out TestExDLLCharacteristics
}{
{
TestDebugIn{
index: 3,
filepath: getAbsoluteFilePath("test/kernel32.dll"),
},
TestExDLLCharacteristics{
debugEntry: DebugEntry{
Struct: ImageDebugDirectory{
Characteristics: 0x0,
TimeDateStamp: 0x38b369c4,
MajorVersion: 0x0,
MinorVersion: 0x0,
Type: 0x14,
SizeOfData: 0x4,
AddressOfRawData: 0x938b0,
PointerToRawData: 0x922b0,
},
Info: DllCharacteristicsExType(0x1),
Type: "Ex.DLL Characteristics",
},
exDLLCharacteristics: "CET Compatible",
},
},
}
for _, tt := range tests {
t.Run(tt.in.filepath, func(t *testing.T) {
ops := Options{Fast: true}
file, err := New(tt.in.filepath, &ops)
if err != nil {
t.Fatalf("New(%s) failed, reason: %v", tt.in.filepath, err)
}
err = file.Parse()
if err != nil {
t.Fatalf("Parse(%s) failed, reason: %v", tt.in.filepath, err)
}
var va, size uint32
if file.Is64 {
oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
dirEntry := oh64.DataDirectory[ImageDirectoryEntryDebug]
va = dirEntry.VirtualAddress
size = dirEntry.Size
} else {
oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
dirEntry := oh32.DataDirectory[ImageDirectoryEntryDebug]
va = dirEntry.VirtualAddress
size = dirEntry.Size
}
err = file.parseDebugDirectory(va, size)
if err != nil {
t.Fatalf("parseExportDirectory(%s) failed, reason: %v",
tt.in.filepath, err)
}
debugEntry := file.Debugs[tt.in.index]
if !reflect.DeepEqual(debugEntry, tt.out.debugEntry) {
t.Fatalf("debug entry assertion failed, got %v, want %v",
debugEntry, tt.out.debugEntry)
}
dllCharacteristicsExString := debugEntry.Info.(DllCharacteristicsExType).String()
if dllCharacteristicsExString != tt.out.exDLLCharacteristics {
t.Fatalf("debug entry DllCharacteristicsEx string assertion failed, got %v, want %v",
dllCharacteristicsExString, tt.out.exDLLCharacteristics)
}
})
}
}
func TestDebugDirectoryVCFeature(t *testing.T) {
type TestVCFeature struct {
debugEntry DebugEntry
}
tests := []struct {
in TestDebugIn
out TestVCFeature
}{
{
TestDebugIn{
index: 1,
filepath: getAbsoluteFilePath("test/00da1a2a9d9ebf447508bf6550f05f466f8eabb4ed6c4f2a524c0769b2d75bc1"),
},
TestVCFeature{
debugEntry: DebugEntry{
Struct: ImageDebugDirectory{
Characteristics: 0x0,
TimeDateStamp: 0x5ef47ea0,
MajorVersion: 0x0,
MinorVersion: 0x0,
Type: 0xc,
SizeOfData: 0x14,
AddressOfRawData: 0x39d58,
PointerToRawData: 0x39158,
},
Info: VCFeature{
PreVC11: 0xa,
CCpp: 0x115,
Gs: 0xe4,
Sdl: 0x0,
GuardN: 0x115,
},
Type: "VC Feature",
},
},
},
}
for _, tt := range tests {
t.Run(tt.in.filepath, func(t *testing.T) {
ops := Options{Fast: true}
file, err := New(tt.in.filepath, &ops)
if err != nil {
t.Fatalf("New(%s) failed, reason: %v", tt.in.filepath, err)
}
err = file.Parse()
if err != nil {
t.Fatalf("Parse(%s) failed, reason: %v", tt.in.filepath, err)
}
var va, size uint32
if file.Is64 {
oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
dirEntry := oh64.DataDirectory[ImageDirectoryEntryDebug]
va = dirEntry.VirtualAddress
size = dirEntry.Size
} else {
oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
dirEntry := oh32.DataDirectory[ImageDirectoryEntryDebug]
va = dirEntry.VirtualAddress
size = dirEntry.Size
}
err = file.parseDebugDirectory(va, size)
if err != nil {
t.Fatalf("parseExportDirectory(%s) failed, reason: %v",
tt.in.filepath, err)
}
debugEntry := file.Debugs[tt.in.index]
if !reflect.DeepEqual(debugEntry, tt.out.debugEntry) {
t.Fatalf("debug entry assertion failed, got %+v, want %+v",
debugEntry, tt.out.debugEntry)
}
})
}
}
func TestDebugDirectoryFPO(t *testing.T) {
type TestFPO struct {
imgDebugEntry ImageDebugDirectory
entriesCount int
debugType string
FPODataIndex int
FPOData FPOData
FPOFrameType string
}
tests := []struct {
in TestDebugIn
out TestFPO
}{
{
TestDebugIn{
index: 1,
filepath: getAbsoluteFilePath("test/jobexec.dll"),
},
TestFPO{
imgDebugEntry: ImageDebugDirectory{
Characteristics: 0x0,
TimeDateStamp: 0x355b8e5f,
MajorVersion: 0x0,
MinorVersion: 0x0,
Type: 0x3,
SizeOfData: 0x840,
AddressOfRawData: 0x0,
PointerToRawData: 0xb310,
},
debugType: "FPO",
entriesCount: 131,
FPODataIndex: 0,
FPOData: FPOData{
OffsetStart: 0x1bc0,
ProcSize: 0x22,
},
FPOFrameType: "FPO",
},
},
{
TestDebugIn{
index: 1,
filepath: getAbsoluteFilePath("test/jobexec.dll"),
},
TestFPO{
imgDebugEntry: ImageDebugDirectory{
Characteristics: 0x0,
TimeDateStamp: 0x355b8e5f,
MajorVersion: 0x0,
MinorVersion: 0x0,
Type: 0x3,
SizeOfData: 0x840,
AddressOfRawData: 0x0,
PointerToRawData: 0xb310,
},
debugType: "FPO",
entriesCount: 131,
FPODataIndex: 2,
FPOData: FPOData{
OffsetStart: 0x1c26,
ProcSize: 0x267,
NumLocals: 0x104,
ParamsSize: 0x1,
PrologLength: 0x16,
SavedRegsCount: 0x3,
HasSEH: 0x0,
UseBP: 0x1,
Reserved: 0x0,
FrameType: 0x3,
},
FPOFrameType: "Non FPO",
},
},
}
for _, tt := range tests {
t.Run(tt.in.filepath, func(t *testing.T) {
ops := Options{Fast: true}
file, err := New(tt.in.filepath, &ops)
if err != nil {
t.Fatalf("New(%s) failed, reason: %v", tt.in.filepath, err)
}
err = file.Parse()
if err != nil {
t.Fatalf("Parse(%s) failed, reason: %v", tt.in.filepath, err)
}
var va, size uint32
if file.Is64 {
oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
dirEntry := oh64.DataDirectory[ImageDirectoryEntryDebug]
va = dirEntry.VirtualAddress
size = dirEntry.Size
} else {
oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
dirEntry := oh32.DataDirectory[ImageDirectoryEntryDebug]
va = dirEntry.VirtualAddress
size = dirEntry.Size
}
err = file.parseDebugDirectory(va, size)
if err != nil {
t.Fatalf("parseExportDirectory(%s) failed, reason: %v", tt.in.filepath, err)
}
imgDebugEntry := file.Debugs[tt.in.index].Struct
if !reflect.DeepEqual(imgDebugEntry, tt.out.imgDebugEntry) {
t.Fatalf("debug entry assertion failed, got %v, want %v",
imgDebugEntry, tt.out.imgDebugEntry)
}
debugTypeString := file.Debugs[tt.in.index].Type
if debugTypeString != tt.out.debugType {
t.Fatalf("debug type assertion failed, got %v, want %v",
debugTypeString, tt.out.debugType)
}
fpo := file.Debugs[tt.in.index].Info.([]FPOData)
entriesCount := len(fpo)
if entriesCount != tt.out.entriesCount {
t.Fatalf("debug entry count failed, got %v, want %v",
entriesCount, tt.out.entriesCount)
}
fpoData := fpo[tt.out.FPODataIndex]
if !reflect.DeepEqual(fpoData, tt.out.FPOData) {
t.Fatalf("debug FPO data entry assertion failed, got %v, want %v",
fpoData, tt.out.FPOData)
}
frameType := fpoData.FrameType.String()
if frameType != tt.out.FPOFrameType {
t.Fatalf("debug FPO frame type string assertion failed, got %v, want %v",
frameType, tt.out.FPOFrameType)
}
})
}
}
func TestDebugSectionAttributes(t *testing.T) {
tests := []struct {
in string
out string
}{
{
".00cfg",
"CFG Check Functions Pointers",
},
{
"__undefined__",
"",
},
}
for _, tt := range tests {
t.Run(tt.out, func(t *testing.T) {
secAttrString := SectionAttributeDescription(tt.in)
if secAttrString != tt.out {
t.Fatalf("debug section attributes description failed, got %v, want %v",
secAttrString, tt.out)
}
})
}
}
================================================
FILE: delayimports.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.
package pe
import (
"encoding/binary"
)
// ImageDelayImportDescriptor represents the _IMAGE_DELAYLOAD_DESCRIPTOR structure.
type ImageDelayImportDescriptor struct {
// As yet, no attribute flags are defined. The linker sets this field to zero
// in the image. This field can be used to extend the record by indicating
// the presence of new fields, or it can be used to indicate behaviors to
// the delay or unload helper functions.
Attributes uint32 `json:"attributes"`
// The name of the DLL to be delay-loaded resides in the read-only data
// section of the image. It is referenced through the szName field.
Name uint32 `json:"name"`
// The handle of the DLL to be delay-loaded is in the data section of the
// image. The phmod field points to the handle. The supplied delay-load
// helper uses this location to store the handle to the loaded DLL.
ModuleHandleRVA uint32 `json:"module_handle_rva"`
// The delay import address table (IAT) is referenced by the delay import
// descriptor through the pIAT field. The delay-load helper updates these
// pointers with the real entry points so that the thunks are no longer in
// the calling loop
ImportAddressTableRVA uint32 `json:"import_address_table_rva"`
// The delay import name table (INT) contains the names of the imports that
// might require loading. They are ordered in the same fashion as the
// function pointers in the IAT.
ImportNameTableRVA uint32 `json:"import_name_table_rva"`
// The delay bound import address table (BIAT) is an optional table of
// IMAGE_THUNK_DATA items that is used along with the timestamp field
// of the delay-load directory table by a post-process binding phase.
BoundImportAddressTableRVA uint32 `json:"bound_import_address_table_rva"`
// The delay unload import address table (UIAT) is an optional table of
// IMAGE_THUNK_DATA items that the unload code uses to handle an explicit
// unload request. It consists of initialized data in the read-only section
// that is an exact copy of the original IAT that referred the code to the
// delay-load thunks. On the unload request, the library can be freed,
// the *phmod cleared, and the UIAT written over the IAT to restore
// everything to its preload state.
UnloadInformationTableRVA uint32 `json:"unload_information_table_rva"`
// 0 if not bound, otherwise, date/time of the target DLL.
TimeDateStamp uint32 `json:"time_date_stamp"`
}
// DelayImport represents an entry in the delay import table.
type DelayImport struct {
Offset uint32 `json:"offset"`
Name string `json:"name"`
Functions []ImportFunction `json:"functions"`
Descriptor ImageDelayImportDescriptor `json:"descriptor"`
}
// Delay-Load Import Tables tables were added to the image to support a uniform
// mechanism for applications to delay the loading of a DLL until the first call
// into that DLL. The delay-load directory table is the counterpart to the
// import directory table.
func (pe *File) parseDelayImportDirectory(rva, size uint32) error {
for {
importDelayDesc := ImageDelayImportDescriptor{}
fileOffset := pe.GetOffsetFromRva(rva)
importDescSize := uint32(binary.Size(importDelayDesc))
err := pe.structUnpack(&importDelayDesc, fileOffset, importDescSize)
// If the RVA is invalid all would blow up. Some EXEs seem to be
// specially nasty and have an invalid RVA.
if err != nil {
return err
}
// If the structure is all zeros, we reached the end of the list.
if importDelayDesc == (ImageDelayImportDescriptor{}) {
break
}
rva += importDescSize
// If the array of thunks is somewhere earlier than the import
// descriptor we can set a maximum length for the array. Otherwise
// just set a maximum length of the size of the file
maxLen := uint32(len(pe.data)) - fileOffset
if rva > importDelayDesc.ImportNameTableRVA ||
rva > importDelayDesc.ImportAddressTableRVA {
if rva < importDelayDesc.ImportNameTableRVA {
maxLen = rva - importDelayDesc.ImportAddressTableRVA
} else if rva < importDelayDesc.ImportAddressTableRVA {
maxLen = rva - importDelayDesc.ImportNameTableRVA
} else {
maxLen = Max(rva-importDelayDesc.ImportNameTableRVA,
rva-importDelayDesc.ImportAddressTableRVA)
}
}
var importedFunctions []ImportFunction
if pe.Is64 {
importedFunctions, err = pe.parseImports64(&importDelayDesc, maxLen)
} else {
importedFunctions, err = pe.parseImports32(&importDelayDesc, maxLen)
}
if err != nil {
return err
}
nameRVA := uint32(0)
if importDelayDesc.Attributes == 0 {
nameRVA = importDelayDesc.Name -
pe.NtHeader.OptionalHeader.(ImageOptionalHeader32).ImageBase
} else {
nameRVA = importDelayDesc.Name
}
dllName := pe.getStringAtRVA(nameRVA, maxLen)
if !IsValidDosFilename(dllName) {
dllName = "*invalid*"
continue
}
pe.DelayImports = append(pe.DelayImports, DelayImport{
Offset: fileOffset,
Name: string(dllName),
Functions: importedFunctions,
Descriptor: importDelayDesc,
})
}
if len(pe.DelayImports) > 0 {
pe.HasDelayImp = true
}
return nil
}
// GetDelayImportEntryInfoByRVA return an import function + index of the entry given
// an RVA.
func (pe *File) GetDelayImportEntryInfoByRVA(rva uint32) (DelayImport, int) {
for _, imp := range pe.DelayImports {
for i, entry := range imp.Functions {
if entry.ThunkRVA == rva {
return imp, i
}
}
}
return DelayImport{}, 0
}
================================================
FILE: delayimports_test.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.
package pe
import (
"reflect"
"testing"
)
type TestDelayImportEntry struct {
entryCount int
entryIndex int
entry DelayImport
}
func TestDelayImportDirectory(t *testing.T) {
tests := []struct {
in string
out TestDelayImportEntry
}{
{
getAbsoluteFilePath("test/000049925c578e5a0883e7d1a8257c1a44feab8f7d9972ace8d0e3fb96612a4c"),
TestDelayImportEntry{
entryCount: 4,
entryIndex: 0,
entry: DelayImport{
Offset: 0x5F7C00,
Name: "kernel32.dll",
Functions: []ImportFunction{
{
Name: "GetLogicalProcessorInformation",
Hint: 0x0,
ByOrdinal: false,
OriginalThunkValue: 0x601192,
ThunkValue: 0xF04E60,
ThunkRVA: 0x6010B4,
OriginalThunkRVA: 0x6010F0,
},
},
Descriptor: ImageDelayImportDescriptor{
Attributes: 0x1,
Name: 0x601184,
ModuleHandleRVA: 0x6010A0,
ImportAddressTableRVA: 0x6010B4,
ImportNameTableRVA: 0x6010F0,
BoundImportAddressTableRVA: 0x60112C,
UnloadInformationTableRVA: 0x601158,
TimeDateStamp: 0x0,
},
},
},
},
}
for _, tt := range tests {
t.Run(tt.in, func(t *testing.T) {
ops := Options{Fast: true}
file, err := New(tt.in, &ops)
if err != nil {
t.Fatalf("New(%s) failed, reason: %v", tt.in, err)
}
err = file.Parse()
if err != nil {
t.Fatalf("Parse(%s) failed, reason: %v", tt.in, err)
}
var va, size uint32
if file.Is64 {
oh64 := file.NtHeader.OptionalHeader.(ImageOptionalHeader64)
dirEntry := oh64.DataDirectory[ImageDirectoryEntryDelayImport]
va = dirEntry.VirtualAddress
size = dirEntry.Size
} else {
oh32 := file.NtHeader.OptionalHeader.(ImageOptionalHeader32)
dirEntry := oh32.DataDirectory[ImageDirectoryEntryDelayImport]
va = dirEntry.VirtualAddress
size = dirEntry.Size
}
err = file.parseDelayImportDirectory(va, size)
if err != nil {
t.Fatalf("parseDelayImportDirectory(%s) failed, reason: %v", tt.in, err)
}
got := file.DelayImports
if len(got) != tt.out.entryCount {
t.Errorf("delay imports entry count assertion failed, got %v, want %v",
len(got), tt.out.entryCount)
}
if len(file.DelayImports) > 0 {
delayImportEntry := file.DelayImports[tt.out.entryIndex]
if !reflect.DeepEqual(delayImportEntry, tt.out.entry) {
t.Errorf("delay import entry assertion failed, got %v, want %v",
delayImportEntry, tt.out.entry)
}
}
})
}
}
================================================
FILE: dosheader.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.
package pe
import (
"encoding/binary"
)
// ImageDOSHeader represents the DOS stub of a PE.
type ImageDOSHeader struct {
// Magic number.
Magic uint16 `json:"magic"`
// Bytes on last page of file.
BytesOnLastPageOfFile uint16 `json:"bytes_on_last_page_of_file"`
// Pages in file.
PagesInFile uint16 `json:"pages_in_file"`
// Relocations.
Relocations uint16 `json:"relocations"`
// Size of header in paragraphs.
SizeOfHeader uint16 `json:"size_of_header"`
// Minimum extra paragraphs needed.
MinExtraParagraphsNeeded uint16 `json:"min_extra_paragraphs_needed"`
// Maximum extra paragraphs needed.
MaxExtraParagraphsNeeded uint16 `json:"max_extra_paragraphs_needed"`
// Initial (relative) SS value.
InitialSS uint16 `json:"initial_ss"`
// Initial SP value.
InitialSP uint16 `json:"initial_sp"`
// Checksum.
Checksum uint16 `json:"checksum"`
// Initial IP value.
InitialIP uint16 `json:"initial_ip"`
// Initial (relative) CS value.
InitialCS uint16 `json:"initial_cs"`
// File address of relocation table.
AddressOfRelocationTable uint16 `json:"address_of_relocation_table"`
// Overlay number.
OverlayNumber uint16 `json:"overlay_number"`
// Reserved words.
ReservedWords1 [4]uint16 `json:"reserved_words_1"`
// OEM identifier.
OEMIdentifier uint16 `json:"oem_identifier"`
// OEM information.
OEMInformation uint16 `json:"oem_information"`
// Reserved words.
ReservedWords2 [10]uint16 `json:"reserved_words_2"`
// File address of new exe header (Elfanew).
AddressOfNewEXEHeader uint32 `json:"address_of_new_exe_header"`
}
// ParseDOSHeader parses the DOS header stub. Every PE file begins with a small
// MS-DOS stub. The need for this arose in the early days of Windows, before a
// significant number of consumers were running it. When executed on a machine
// without Windows, the program could at least print out a message saying that
// Windows was required to run the executable.
func (pe *File) ParseDOSHeader() (err error) {
offset := uint32(0)
size := uint32(binary.Size(pe.DOSHeader))
err = pe.structUnpack(&pe.DOSHeader, offset, size)
if err != nil {
return err
}
// It can be ZM on an (non-PE) EXE.
// These executables still work under XP via ntvdm.
if pe.DOSHeader.Magic != ImageDOSSignature &&
pe.DOSHeader.Magic != ImageDOSZMSignature {
return ErrDOSMagicNotFound
}
// `e_lfanew` is the only required element (besides the signature) of the
// DOS header to turn the EXE into a PE. It is is a relative offset to the
// NT Headers. It can't be null (signatures would overlap).
// Can be 4 at minimum.
if pe.DOSHeader.AddressOfNewEXEHeader < 4 ||
pe.DOSHeader.AddressOfNewEXEHeader > pe.size {
return ErrInvalidElfanewValue
}
// tiny pe has a e_lfanew of 4, which means the NT Headers is overlapping
// the DOS Header.
if pe.DOSHeader.AddressOfNewEXEHeader <= 0x3c {
pe.Anomalies = append(pe.Anomalies, AnoPEHeaderOverlapDOSHeader)
}
pe.HasDOSHdr = true
return nil
}
================================================
FILE: dosheader_test.go
================================================
// Copyright 2022 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.
package pe
import (
"testing"
)
type TestDOSHeader struct {
imageDOSHeader ImageDOSHeader
}
func TestParseDOSHeader(t *testing.T) {
tests := []struct {
in string
out TestDOSHeader
}{
{
getAbsoluteFilePath("test/putty.exe"),
TestDOSHeader{
imageDOSHeader: ImageDOSHeader{
Magic: 0x5a4d,
BytesOnLastPageOfFile: 0x78,
PagesInFile: 0x1,
Relocations: 0x0,
SizeOfHeader: 0x4,
MinExtraParagraphsNeeded: 0x0,
MaxExtraParagraphsNeeded: 0x0,
InitialSS: 0x0,
InitialSP: 0x0,
Checksum: 0x0,
InitialIP: 0x0,
InitialCS: 0x0,
AddressOfRelocationTable: 0x40,
OverlayNumber: 0x0,
ReservedWords1: [4]uint16{},
OEMIdentifier: 0x0,
OEMInformation: 0x0,
ReservedWords2: [10]uint16{},
AddressOfNewEXEHeader: 0x78,
},
},
},
}
for _, tt := range tests {
t.Run(tt.in, func(t *testing.T) {
ops := Options{Fast: true}
file, err := New(tt.in, &ops)
if err != nil {
t.Fatalf("New(%s) failed, reason: %v", tt.in, err)
}
err = file.ParseDOSHeader()
if err != nil {
t.Fatalf("Parse(%s) failed, reason: %v", tt.in, err)
}
got := file.DOSHeader
if got != tt.out.imageDOSHeader {
t.Errorf("parse DOS header assertion failed, got %v, want %v", got,
tt.out.imageDOSHeader)
}
})
}
}
func TestParseDOSHeaderNonMZ(t *testing.T) {
tests := []struct {
in string
out error
}{
{
// This is an ELF file.
getAbsoluteFilePath("test/look"),
ErrDOSMagicNotFound,
},
}
for _, tt := range tests {
t.Run(tt.in, func(t *testing.T) {
ops := Options{Fast: true}
file, err := New(tt.in, &ops)
if err != nil {
t.Fatalf("New(%s) failed, reason: %v", tt.in, err)
}
err = file.ParseDOSHeader()
if err != tt.out {
t.Fatalf("parsing DOS header failed, got %v, want %v", err, tt.out)
}
})
}
}
================================================
FILE: dotnet.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.
package pe
import (
"encoding/binary"
)
// References
// https://www.ntcore.com/files/dotnetformat.htm
// COMImageFlagsType represents a COM+ header entry point flag type.
type COMImageFlagsType uint32
// COM+ Header entry point flags.
const (
// The image file contains IL code only, with no embedded native unmanaged
// code except the start-up stub (which simply executes an indirect jump to
// the CLR entry point).
COMImageFlagsILOnly = 0x00000001
// The image file can be loaded only into a 32-bit process.
COMImageFlags32BitRequired = 0x00000002
// This flag is obsolete and should not be set. Setting it—as the IL
// assembler allows, using the .corflags directive—will render your module
// un-loadable.
COMImageFlagILLibrary = 0x00000004
// The image file is protected with a strong name signature.
COMImageFlagsStrongNameSigned = 0x00000008
// The executable’s entry point is an unmanaged method. The EntryPointToken/
// EntryPointRVA field of the CLR header contains the RVA of this native
// method. This flag was introduced in version 2.0 of the CLR.
COMImageFlagsNativeEntrypoint = 0x00000010
// The CLR loader and the JIT compiler are required to track debug
// information about the methods. This flag is not used.
COMImageFlagsTrackDebugData = 0x00010000
// The image file can be loaded into any process, but preferably into a
// 32-bit process. This flag can be only set together with flag
// COMIMAGE_FLAGS_32BITREQUIRED. When set, these two flags mean the image
// is platformneutral, but prefers to be loaded as 32-bit when possible.
// This flag was introduced in CLR v4.0
COMImageFlags32BitPreferred = 0x00020000
)
// V-table constants.
const (
// V-table slots are 32-bits in size.
CORVTable32Bit = 0x01
// V-table slots are 64-bits in size.
CORVTable64Bit = 0x02
// The thunk created by the common language runtime must provide data
// marshaling between managed and unmanaged code.
CORVTableFromUnmanaged = 0x04
// The thunk created by the common language runtime must provide data
// marshaling between managed and unmanaged code. Current appdomain should
// be selected to dispatch the call.
CORVTableFromUnmanagedRetainAppDomain = 0x08
// Call most derived method described by
CORVTableCallMostDerived = 0x10
)
// Metadata Tables constants.
const (
// The current module descriptor.
Module = 0
// Class reference descriptors.
TypeRef = 1
// Class or interface definition descriptors.
TypeDef = 2
// A class-to-fields lookup table, which does not exist in optimized
// metadata (#~ stream).
FieldPtr = 3
// Field definition descriptors.
Field = 4
// A class-to-methods lookup table, which does not exist in
// optimized metadata (#~ stream).
MethodPtr = 5
// Method definition descriptors.
MethodDef = 6
// A method-to-parameters lookup table, which does not exist in optimized
// metadata (#~ stream).
ParamPtr = 7
// Parameter definition descriptors.
Param = 8
// Interface implementation descriptors.
InterfaceImpl = 9
// Member (field or method) reference descriptors.
MemberRef = 10
// Constant value descriptors that map the default values stored in the
// #Blob stream to respective fields, parameters, and properties.
Constant = 11
// Custom attribute descriptors.
CustomAttribute = 12
// Field or parameter marshaling descriptors for managed/unmanaged
// inter-operations.
FieldMarshal = 13
// Security descriptors.
DeclSecurity = 14
// Class layout descriptors that hold information about how the loader
// should lay out respective classes.
ClassLayout = 15
// Field layout descriptors that specify the offset or ordinal of
// individual fields.
FieldLayout = 16
// Stand-alone signature descriptors. Signatures per se are used in two
// capacities: as composite signatures of local variables of methods and as
// parameters of the call indirect (calli) IL instruction.
StandAloneSig = 17
// A class-to-events mapping table. This is not an intermediate lookup
// table, and it does exist in optimized metadata.
EventMap = 18
// An event map–to–events lookup table, which does not exist in optimized
// metadata (#~ stream).
EventPtr = 19
// Event descriptors.
Event = 20
// A class-to-properties mapping table. This is not an intermediate lookup
// table, and it does exist in optimized metadata.
PropertyMap = 21
// A property map–to–properties lookup table, which does not exist in
// optimized metadata (#~ stream).
PropertyPtr = 22
// Property descriptors.
Property = 23
// Method semantics descriptors that hold information about which method is
// associated with a specific property or event and in what capacity.
MethodSemantics = 24
// Method implementation descriptors.
MethodImpl = 25
// Module reference descriptors.
ModuleRef = 26
// Type specification descriptors.
TypeSpec = 27
// Implementation map descriptors used for the platform invocation
// (P/Invoke) type of managed/unmanaged code inter-operation.
ImplMap = 28
// Field-to-data mapping descriptors.
FieldRVA = 29
// Edit-and-continue log descriptors that hold information about what
// changes have been made to specific metadata items during in-memory
// editing. This table does not exist in optimized metadata (#~ stream)
ENCLog = 30
// Edit-and-continue mapping descriptors. This table does not exist in
// optimized metadata (#~ stream).
ENCMap = 31
// The current assembly descriptor, which should appear only in the prime
// module metadata.
Assembly = 32
// This table is unused.
AssemblyProcessor = 33
// This table is unused.
AssemblyOS = 34
// Assembly reference descriptors.
AssemblyRef = 35
// This table is unused.
AssemblyRefProcessor = 36
// This table is unused.
AssemblyRefOS = 37
// File descriptors that contain information about other files in the
// current assembly.
FileMD = 38
// Exported type descriptors that contain information about public classes
// exported by the current assembly, which are declared in other modules of
// the assembly. Only the prime module of the assembly should carry this
// table.
ExportedType = 39
// Managed resource descriptors.
ManifestResource = 40
// Nested class descriptors that provide mapping of nested classes to their
// respective enclosing classes.
NestedClass = 41
// Type parameter descriptors for generic (parameterized) classes and
// methods.
GenericParam = 42
// Generic method instantiation descriptors.
MethodSpec = 43
// Descriptors of constraints specified for type parameters of generic
// classes and methods
GenericParamConstraint = 44
)
// Heaps Streams Bit Positions.
const (
StringStream = 0
GUIDStream = 1
BlobStream = 2
)
// MetadataTableIndexToString returns the string representation of the metadata
// table index.
func MetadataTableIndexToString(k int) string {
metadataTablesMap := map[int]string{
Module: "Module",
TypeRef: "TypeRef",
TypeDef: "TypeDef",
FieldPtr: "FieldPtr",
Field: "Field",
MethodPtr: "MethodPtr",
MethodDef: "MethodDef",
ParamPtr: "ParamPtr",
Param: "Param",
InterfaceImpl: "InterfaceImpl",
MemberRef: "MemberRef",
Constant: "Constant",
CustomAttribute: "CustomAttribute",
FieldMarshal: "FieldMarshal",
DeclSecurity: "DeclSecurity",
ClassLayout: "ClassLayout",
FieldLayout: "FieldLayout",
StandAloneSig: "StandAloneSig",
EventMap: "EventMap",
EventPtr: "EventPtr",
Event: "Event",
PropertyMap: "PropertyMap",
PropertyPtr: "PropertyPtr",
Property: "Property",
MethodSemantics: "MethodSemantics",
MethodImpl: "MethodImpl",
ModuleRef: "ModuleRef",
TypeSpec: "TypeSpec",
ImplMap: "ImplMap",
FieldRVA: "FieldRVA",
ENCLog: "ENCLog",
ENCMap: "ENCMap",
Assembly: "Assembly",
AssemblyProcessor: "AssemblyProcessor",
AssemblyOS: "AssemblyOS",
AssemblyRef: "AssemblyRef",
AssemblyRefProcessor: "AssemblyRefProcessor",
AssemblyRefOS: "AssemblyRefOS",
FileMD: "File",
ExportedType: "ExportedType",
ManifestResource: "ManifestResource",
NestedClass: "NestedClass",
GenericParam: "GenericParam",
MethodSpec: "MethodSpec",
GenericParamConstraint: "GenericParamConstraint",
}
if value, ok := metadataTablesMap[k]; ok {
return value
}
return ""
}
// GetMetadataStreamIndexSize returns the size of indexes to read into a
// particular heap.
func (pe *File) GetMetadataStreamIndexSize(BitPosition int) int {
// The `Heaps` field is a bit vector that encodes how wide indexes into the
// various heaps are:
// - If bit 0 is set, indexes into the "#String" heap are 4 bytes wide;
// - if bit 1 is set, indexes into the "#GUID" heap are 4 bytes wide;
// - if bit 2 is set, indexes into the "#Blob" heap are 4 bytes wide.
heaps := pe.CLR.MetadataTablesStreamHeader.Heaps
if IsBitSet(uint64(heaps), BitPosition) {
return 4
}
// Conversely, if the HeapSizes bit for a particular heap is not set,
// indexes into that heap are 2 bytes wide.
return 2
}
// ImageDataDirectory represents the directory format.
type ImageDataDirectory struct {
// The relative virtual address of the table.
VirtualAddress uint32 `json:"virtual_address"`
// The size of the table, in bytes.
Size uint32 `json:"size"`
}
// ImageCOR20Header represents the CLR 2.0 header structure.
type ImageCOR20Header struct {
// Size of the header in bytes.
Cb uint32 `json:"cb"`
// Major number of the minimum version of the runtime required to run the
// program.
MajorRuntimeVersion uint16 `json:"major_runtime_version"`
// Minor number of the version of the runtime required to run the program.
MinorRuntimeVersion uint16 `json:"minor_runtime_version"`
// RVA and size of the metadata.
MetaData ImageDataDirectory `json:"meta_data"`
// Bitwise flags indicating attributes of this executable.
Flags COMImageFlagsType `json:"flags"`
// Metadata identifier (token) of the entry point for the image file; can
// be 0 for DLL images. This field identifies a method belonging to this
// module or a module containing the entry point method.
// In images of version 2.0 and newer, this field may contain RVA of the
// embedded native entry point method.
// union {
//
// If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is not set,
// EntryPointToken represents a managed entrypoint.
// DWORD EntryPointToken;
//
// If COMIMAGE_FLAGS_NATIVE_ENTRYPOINT is set,
// EntryPointRVA represents an RVA to a native entrypoint
// DWORD EntryPointRVA;
//};
EntryPointRVAorToken uint32 `json:"entry_point_rva_or_token"`
// This is the blob of managed resources. Fetched using
// code:AssemblyNative.GetResource and code:PEFile.GetResource and accessible
// from managed code from System.Assembly.GetManifestResourceStream. The
// metadata has a table that maps names to offsets into this blob, so
// logically the blob is a set of resources.
Resources ImageDataDirectory `json:"resources"`
// RVA and size of the hash data for this PE file, used by the loader for
// binding and versioning. IL assemblies can be signed with a public-private
// key to validate who created it. The signature goes here if this feature
// is used.
StrongNameSignature ImageDataDirectory `json:"strong_name_signature"`
// RVA and size of the Code Manager table. In the existing releases of the
// runtime, this field is reserved and must be set to 0.
CodeManagerTable ImageDataDirectory `json:"code_manager_table"`
// RVA and size in bytes of an array of virtual table (v-table) fixups.
// Among current managed compilers, only the VC++ linker and the IL
// assembler can produce this array.
VTableFixups ImageDataDirectory `json:"vtable_fixups"`
// RVA and size of an array of addresses of jump thunks. Among managed
// compilers, only the VC++ of versions pre-8.0 could produce this table,
// which allows the export of unmanaged native methods embedded in the
// managed PE file. In v2.0+ of CLR this entry is obsolete and must be set
// to 0.
ExportAddressTableJumps ImageDataDirectory `json:"export_address_table_jumps"`
// Reserved for precompiled images; set to 0
// NGEN images it points at a code:CORCOMPILE_HEADER structure
ManagedNativeHeader ImageDataDirectory `json:"managed_native_header"`
}
// ImageCORVTableFixup defines the v-table fixups that contains the
// initializing information necessary for the runtime to create the thunks.
// Non VOS v-table entries. Define an array of these pointed to by
// IMAGE_COR20_HEADER.VTableFixups. Each entry describes a contiguous array of
// v-table slots. The slots start out initialized to the meta data token value
// for the method they need to call. At image load time, the CLR Loader will
// turn each entry into a pointer to machine code for the CPU and can be
// called directly.
type ImageCORVTableFixup struct {
RVA uint32 `json:"rva"` // Offset of v-table array in image.
Count uint16 `json:"count"` // How many entries at location.
Type uint16 `json:"type"` // COR_VTABLE_xxx type of entries.
}
// MetadataHeader consists of a storage signature and a storage header.
type MetadataHeader struct {
// The storage signature, which must be 4-byte aligned:
// ”Magic” signature for physical metadata, currently 0x424A5342, or, read
// as characters, BSJB—the initials of four “founding fathers” Brian Harry,
// Susa Radke-Sproull, Jason Zander, and Bill Evans, who started the
// runtime development in 1998.
Signature uint32 `json:"signature"`
// Major version.
MajorVersion uint16 `json:"major_version"`
// Minor version.
MinorVersion uint16 `json:"minor_version"`
// Reserved; set to 0.
ExtraData uint32 `json:"extra_data"`
// Length of the version string.
VersionString uint32 `json:"version_string"`
// Version string.
Version string `json:"version"`
// The storage header follows the storage signature, aligned on a 4-byte
// boundary.
//
// Reserved; set to 0.
Flags uint8 `json:"flags"`
// Another byte used for [padding]
// Number of streams.
Streams uint16 `json:"streams"`
}
// MetadataStreamHeader represents a Metadata Stream Header Structure.
type MetadataStreamHeader struct {
// Offset in the file for this stream.
Offset uint32 `json:"offset"`
// Size of the stream in bytes.
Size uint32 `json:"size"`
// Name of the stream; a zero-terminated ASCII string no longer than 31
// characters (plus zero terminator). The name might be shorter, in which
// case the size of the stream header is correspondingly reduced, padded to
// the 4-byte boundary.
Name string `json:"name"`
}
// MetadataTableStreamHeader represents the Metadata Table Stream Header Structure.
type MetadataTableStreamHeader struct {
// Reserved; set to 0.
Reserved uint32 `json:"reserved"`
// Major version of the table schema (1 for v1.0 and v1.1; 2 for v2.0 or later).
MajorVersion uint8 `json:"major_version"`
// Minor version of the table schema (0 for all versions).
MinorVersion uint8 `json:"minor_version"`
// Binary flags indicate the offset sizes to be used within the heaps.
// 4-byte unsigned integer offset is indicated by:
// - 0x01 for a string heap, 0x02 for a GUID heap, and 0x04 for a blob heap.
// If a flag is not set, the respective heap offset is a 2-byte unsigned integer.
// A #- stream can also have special flags set:
// - flag 0x20, indicating that the stream contains only changes made
// during an edit-and-continue session, and;
// - flag 0x80, indicating that the metadata might contain items marked as
// deleted.
Heaps uint8 `json:"heaps"`
// Bit width of the maximal record index to all tables of the metadata;
// calculated at run time (during the metadata stream initialization).
RID uint8 `json:"rid"`
// Bit vector of present tables, each bit representing one table (1 if
// present).
MaskValid uint64 `json:"mask_valid"`
// Bit vector of sorted tables, each bit representing a respective table (1
// if sorted)
Sorted uint64 `json:"sorted"`
}
// MetadataTable represents the content of a particular table in the metadata.
// The metadata schema defines 45 tables.
type MetadataTable struct {
// The name of the table.
Name string `json:"name"`
// Number of columns in the table.
CountCols uint32 `json:"count_cols"`
// Every table has a different layout, defined in the ECMA-335 spec.
// Content abstract the type each table is pointing to.
Content interface{} `json:"content"`
}
// CLRData embeds the Common Language Runtime Header structure as well as the
// Metadata header structure.
type CLRData struct {
CLRHeader ImageCOR20Header `json:"clr_header"`
MetadataHeader MetadataHeader `json:"metadata_header"`
MetadataStreamHeaders []MetadataStreamHeader `json:"metadata_stream_headers"`
MetadataStreams map[string][]byte `json:"-"`
MetadataTablesStreamHeader MetadataTableStreamHeader `json:"metadata_tables_stream_header"`
MetadataTables map[int]*MetadataTable `json:"metadata_tables"`
StringStreamIndexSize int `json:"-"`
GUIDStreamIndexSize int `json:"-"`
BlobStreamIndexSize int `json:"-"`
}
func (pe *File) parseMetadataStream(off, size uint32) (MetadataTableStreamHeader, error) {
mdTableStreamHdr := MetadataTableStreamHeader{}
if size == 0 {
return mdTableStreamHdr, nil
}
mdTableStreamHdrSize := uint32(binary.Size(mdTableStreamHdr))
err := pe.structUnpack(&mdTableStreamHdr, off, mdTableStreamHdrSize)
if err != nil {
return mdTableStreamHdr, err
}
return mdTableStreamHdr, nil
}
func (pe *File) parseMetadataHeader(offset, size uint32) (MetadataHeader, error) {
var err error
mh := MetadataHeader{}
if mh.Signature, err = pe.ReadUint32(offset); err != nil {
return mh, err
}
if mh.MajorVersion, err = pe.ReadUint16(offset + 4); err != nil {
return mh, err
}
if mh.MinorVersion, err = pe.ReadUint16(offset + 6); err != nil {
return mh, err
}
if mh.ExtraData, err = pe.ReadUint32(offset + 8); err != nil {
return mh, err
}
if mh.VersionString, err = pe.ReadUint32(offset + 12); err != nil {
return mh, err
}
mh.Version, err = pe.getStringAtOffset(offset+16, mh.VersionString)
if err != nil {
return mh, err
}
offset += 16 + mh.VersionString
if mh.Flags, err = pe.ReadUint8(offset); err != nil {
return mh, err
}
if mh.Streams, err = pe.ReadUint16(offset + 2); err != nil {
return mh, err
}
return mh, err
}
// The 15th directory entry of the PE header contains the RVA and size of the
// runtime header in the image file. The runtime header, which contains all of
// the runtime-specific data entries and other information, should reside in a
// read-only section of the image file. The IL assembler puts the common
// language runtime header in the .text section.
func (pe *File) parseCLRHeaderDirectory(rva, size uint32) error {
clrHeader := ImageCOR20Header{}
offset := pe.GetOffsetFromRva(rva)
err := pe.structUnpack(&clrHeader, offset, size)
if err != nil {
return err
}
pe.CLR.CLRHeader = clrHeader
if clrHeader.MetaData.VirtualAddress == 0 || clrHeader.MetaData.Size == 0 {
return nil
}
// If we get a CLR header, we assume that this is enough
// to say we have a CLR data to show even if parsing
// other structures fails later.
pe.HasCLR = true
if pe.opts.OmitCLRMetadata {
return nil
}
offset = pe.GetOffsetFromRva(clrHeader.MetaData.VirtualAddress)
mh, err := pe.parseMetadataHeader(offset, clrHeader.MetaData.Size)
if err != nil {
return err
}
pe.CLR.MetadataHeader = mh
pe.CLR.MetadataStreams = make(map[string][]byte)
offset += 16 + mh.VersionString + 4
// Immediately following the MetadataHeader is a series of Stream Headers.
// A “stream” is to the metadata what a “section” is to the assembly. The
// NumberOfStreams property indicates how many StreamHeaders to read.
mdStreamHdrOff := uint32(0)
mdStreamHdrSize := uint32(0)
for i := uint16(0); i < mh.Streams; i++ {
sh := MetadataStreamHeader{}
if sh.Offset, err = pe.ReadUint32(offset); err != nil {
return err
}
if sh.Size, err = pe.ReadUint32(offset + 4); err != nil {
return err
}
// Name requires a special treatment.
offset += 8
for j := uint32(0); j <= 32; j++ {
var c uint8
if c, err = pe.ReadUint8(offset); err != nil {
return err
}
offset++
if c == 0 && (j+1)%4 == 0 {
break
}
if c != 0 {
sh.Name += string(c)
}
}
// The streams #~ and #- are mutually exclusive; that is, the metadata
// structure of the module is either optimized or un-optimized; it
// cannot be both at the same time or be something in between.
if sh.Name == "#~" || sh.Name == "#-" {
mdStreamHdrOff = sh.Offset
mdStreamHdrSize = sh.Size
}
rva = clrHeader.MetaData.VirtualAddress + sh.Offset
start := pe.GetOffsetFromRva(rva)
// Some malformed/Corrupt PEs has invalid sizes on sh.
mdStreamBytes := make([]byte, 0)
if start+sh.Size <= uint32(len(pe.data)) {
mdStreamBytes = pe.data[start : start+sh.Size]
}
// Save the stream into a map <string> []byte.
pe.CLR.MetadataStreams[sh.Name] = mdStreamBytes
pe.CLR.MetadataStreamHeaders = append(pe.CLR.MetadataStreamHeaders, sh)
}
// Get the Metadata Table Stream.
if mdStreamHdrSize == 0 {
return nil
}
// The .Offset indicated by the stream header is an RVA relative to the
// metadataDirectoryAddress in the CLRHeader.
rva = clrHeader.MetaData.VirtualAddress + mdStreamHdrOff
offset = pe.GetOffsetFromRva(rva)
mdTableStreamHdr, err := pe.parseMetadataStream(offset, mdStreamHdrSize)
if err != nil {
return nil
}
pe.CLR.MetadataTablesStreamHeader = mdTableStreamHdr
// Get the size of indexes of #String", "#GUID" and "#Blob" streams.
pe.CLR.StringStreamIndexSize = pe.GetMetadataStreamIndexSize(StringStream)
pe.CLR.GUIDStreamIndexSize = pe.GetMetadataStreamIndexSize(GUIDStream)
pe.CLR.BlobStreamIndexSize = pe.GetMetadataStreamIndexSize(BlobStream)
// This header is followed by a sequence of 4-byte unsigned integers
// indicating the number of records in each table marked 1 in the MaskValid
// bit vector.
offset += uint32(binary.Size(mdTableStreamHdr))
pe.CLR.MetadataTables = make(map[int]*MetadataTable)
for i := 0; i <= GenericParamConstraint; i++ {
if IsBitSet(mdTableStreamHdr.MaskValid, i) {
mdTable := MetadataTable{}
mdTable.Name = MetadataTableIndexToString(i)
mdTable.CountCols, err = pe.ReadUint32(offset)
if err != nil {
break
}
offset += 4
pe.CLR.MetadataTables[i] = &mdTable
}
}
// Parse the metadata tables.
for tableIndex := 0; tableIndex <= GenericParamConstraint; tableIndex++ {
table, ok := pe.CLR.MetadataTables[tableIndex]
if !ok {
continue
}
n := uint32(0)
switch tableIndex {
case Module: // 0x00
table.Content, n, err = pe.parseMetadataModuleTable(offset)
case TypeRef: // 0x01
table.Content, n, err = pe.parseMetadataTypeRefTable(offset)
case TypeDef: // 0x02
table.Content, n, err = pe.parseMetadataTypeDefTable(offset)
case Field: // 0x04
table.Content, n, err = pe.parseMetadataFieldTable(offset)
case MethodDef: // 0x06
table.Content, n, err = pe.parseMetadataMethodDefTable(offset)
case Param: // 0x08
table.Content, n, err = pe.parseMetadataParamTable(offset)
case InterfaceImpl: // 0x09
table.Content, n, err = pe.parseMetadataInterfaceImplTable(offset)
case MemberRef: // 0x0a
table.Content, n, err = pe.parseMetadataMemberRefTable(offset)
case Constant: // 0x0b
table.Content, n, err = pe.parseMetadataConstantTable(offset)
case CustomAttribute: // 0x0c
table.Content, n, err = pe.parseMetadataCustomAttributeTable(offset)
case FieldMarshal: // 0x0d
table.Content, n, err = pe.parseMetadataFieldMarshalTable(offset)
case DeclSecurity: // 0x0e
table.Content, n, err = pe.parseMetadataDeclSecurityTable(offset)
case ClassLayout: // 0x0f
table.Content, n, err = pe.parseMetadataClassLayoutTable(offset)
case FieldLayout: // 0x10
table.Content, n, err = pe.parseMetadataFieldLayoutTable(offset)
case StandAloneSig: // 0x11
table.Content, n, err = pe.parseMetadataStandAloneSignTable(offset)
case EventMap: // 0x12
table.Content, n, err = pe.parseMetadataEventMapTable(offset)
case Event: // 0x14
table.Content, n, err = pe.parseMetadataEventTable(offset)
case PropertyMap: // 0x15
table.Content, n, err = pe.parseMetadataPropertyMapTable(offset)
case Property: // 0x17
table.Content, n, err = pe.parseMetadataPropertyTable(offset)
case MethodSemantics: // 0x18
table.Content, n, err = pe.parseMetadataMethodSemanticsTable(offset)
case MethodImpl: // 0x19
table.Content, n, err = pe.parseMetadataMethodImplTable(offset)
case ModuleRef: // 0x1a
table.Content, n, err = pe.parseMetadataModuleRefTable(offset)
case TypeSpec: // 0x1b
table.Content, n, err = pe.parseMetadataTypeSpecTable(offset)
case ImplMap: // 0x1c
table.Content, n, err = pe.parseMetadataImplMapTable(offset)
case FieldRVA: // 0x1d
table.Content, n, err = pe.parseMetadataFieldRVATable(offset)
case Assembly: // 0x20
table.Content, n, err = pe.parseMetadataAssemblyTable(offset)
case AssemblyRef: // 0x23
table.Content, n, err = pe.parseMetadataAssemblyRefTable(offset)
case ExportedType: // 0x27
table.Content, n, err = pe.parseMetadataExportedTypeTable(offset)
case ManifestResource: // 0x28
table.Content, n, err = pe.parseMetadataManifestResourceTable(offset)
case NestedClass: // 0x29
table.Content, n, err = pe.parseMetadataNestedClassTable(offset)
case GenericParam: // 0x2a
table.Content, n, err = pe.parseMetadataGenericParamTable(offset)
case MethodSpec: // 0x2b
table.Content, n, err = pe.parseMetadataMethodSpecTable(offset)
case GenericParamConstraint: // 0x2c
table.Content, n, err = pe.parseMetadataGenericParamConstraintTable(offset)
case FileMD: // 0x26
table.Content, n, err = pe.parseMetadataFileTable(offset)
default:
pe.logger.Warnf("unhandled metadata table %d %s offset 0x%x cols %d",
tableIndex, MetadataTableIndexToString(tableIndex), offset, table.CountCols)
}
if err != nil {
pe.logger.Warnf("parsing metadata table %s failed with %v",
MetadataTableIndexToString(tableIndex), err)
}
offset += n
}
return nil
}
// String returns a string interpretation of a COMImageFlags type.
func (flags COMImageFlagsType) String() []string {
COMImageFlags := map[COMImageFlagsType]string{
COMImageFlagsILOnly: "IL Only",
COMImageFlags32BitRequired: "32-Bit Required",
COMImageFlagILLibrary: "IL Library",
COMImageFlagsStrongNameSigned: "Strong Name Signed",
COMImageFlagsNativeEntrypoint: "Native Entrypoint",
COMImageFlagsTrackDebugData: "Track Debug Data",
COMImageFlags32BitPreferred: "32-Bit Preferred",
}
var values []string
for k, v := range COMImageFlags {
if (k & flags) == k {
values = append(values, v)
}
}
return values
}
================================================
FILE: dotnet_helper.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.
package pe
const (
// these are intentionally made so they do not collide with StringStream, GUIDStream, and BlobStream
// they are used only for the getCodedIndexSize function
idxStringStream = iota + 100
idxGUIDStream
idxBlobStream
)
type codedidx struct {
tagbits uint8
idx []int
}
var (
idxTypeDefOrRef = codedidx{tagbits: 2, idx: []int{TypeDef, TypeRef, TypeSpec}}
idxResolutionScope = codedidx{tagbits: 2, idx: []int{Module, ModuleRef, AssemblyRef, TypeRef}}
idxMemberRefParent = codedidx{tagbits: 3, idx: []int{TypeDef, TypeRef, ModuleRef, MethodDef, TypeSpec}}
idxHasConstant = codedidx{tagbits: 2, idx: []int{Field, Param, Property}}
idxHasCustomAttributes = codedidx{tagbits: 5, idx: []int{MethodDef, Field, TypeRef, TypeDef, Param, InterfaceImpl, MemberRef, Module, DeclSecurity, Property, Event, StandAloneSig, ModuleRef, TypeSpec, Assembly, AssemblyRef, FileMD, ExportedType, ManifestResource, GenericParam, GenericParamConstraint, MethodSpec}}
idxCustomAttributeType = codedidx{tagbits: 3, idx: []int{MethodDef, MemberRef}}
idxHasFieldMarshall = codedidx{tagbits: 1, idx: []int{Field, Param}}
idxHasDeclSecurity = codedidx{tagbits: 2, idx: []int{TypeDef, MethodDef, Assembly}}
idxHasSemantics = codedidx{tagbits: 1, idx: []int{Event, Property}}
idxMethodDefOrRef = codedidx{tagbits: 1, idx: []int{MethodDef, MemberRef}}
idxMemberForwarded = codedidx{tagbits: 1, idx: []int{Field, MethodDef}}
idxImplementation = codedidx{tagbits: 2, idx: []int{FileMD, AssemblyRef, ExportedType}}
idxTypeOrMethodDef = codedidx{tagbits: 1, idx: []int{TypeDef, MethodDef}}
idxField = codedidx{tagbits: 0, idx: []int{Field}}
idxMethodDef = codedidx{tagbits: 0, idx: []int{MethodDef}}
idxParam = codedidx{tagbits: 0, idx: []int{Param}}
idxTypeDef = codedidx{tagbits: 0, idx: []int{TypeDef}}
idxEvent = codedidx{tagbits: 0, idx: []int{Event}}
idxProperty = codedidx{tagbits: 0, idx: []int{Property}}
idxModuleRef = codedidx{tagbits: 0, idx: []int{ModuleRef}}
idxGenericParam = codedidx{tagbits: 0, idx: []int{GenericParam}}
idxString = codedidx{tagbits: 0, idx: []int{idxStringStream}}
idxBlob = codedidx{tagbits: 0, idx: []int{idxBlobStream}}
idxGUID = codedidx{tagbits: 0, idx: []int{idxGUIDStream}}
)
func (pe *File) getCodedIndexSize(tagbits uint32, idx ...int) uint32 {
// special case String/GUID/Blob streams
switch idx[0] {
case int(idxStringStream):
return uint32(pe.GetMetadataStreamIndexSize(StringStream))
case int(idxGUIDStream):
return uint32(pe.GetMetadataStreamIndexSize(GUIDStream))
case int(idxBlobStream):
return uint32(pe.GetMetadataStreamIndexSize(BlobStream))
}
// now deal with coded indices or single table
var maxIndex16 uint32 = 1 << (16 - tagbits)
var maxColumnCount uint32
for _, tblidx := range idx {
tbl, ok := pe.CLR.MetadataTables[tblidx]
if ok {
if tbl.CountCols > maxColumnCount {
maxColumnCount = tbl.CountCols
}
}
}
if maxColumnCount >= maxIndex16 {
return 4
}
return 2
}
func (pe *File) readFromMetadataStream(cidx codedidx, off uint32, out *uint32) (uint32, error) {
indexSize := pe.getCodedIndexSize(uint32(cidx.tagbits), cidx.idx...)
var data uint32
var err error
switch indexSize {
case 2:
d, err := pe.ReadUint16(off)
if err != nil {
return 0, err
}
data = uint32(d)
case 4:
data, err = pe.ReadUint32(off)
if err != nil {
return 0, err
}
}
*out = data
return uint32(indexSize), nil
}
================================================
FILE: dotnet_metadata_tables.go
================================================
// Copyright 2018 Saferwall. All rights reserved.
// Use of this source code is governed by Apache v2 license
// license that can be found in the LICENSE file.
package pe
// the struct definition and comments are from the ECMA-335 spec 6th edition
// https://www.ecma-international.org/wp-content/uploads/ECMA-335_6th_edition_june_2012.pdf
// Module 0x00
type ModuleTableRow struct {
// a 2-byte value, reserved, shall be zero
Generation uint16 `json:"generation"`
// an index into the String heap
Name uint32 `json:"name"`
// an index into the Guid heap; simply a Guid used to distinguish between
// two versions of the same module
Mvid uint32 `json:"mvid"`
// an index into the Guid heap; reserved, shall be zero
EncID uint32 `json:"enc_id"`
// an index into the Guid heap; reserved, shall be zero
EncBaseID uint32 `json:"enc_base_id"`
}
// Module 0x00
func (pe *File) parseMetadataModuleTable(off uint32) ([]ModuleTableRow, uint32, error) {
var err error
var indexSize uint32
var n uint32
rowCount := int(pe.CLR.MetadataTables[Module].CountCols)
rows := make([]ModuleTableRow, rowCount)
for i := 0; i < rowCount; i++ {
if rows[i].Generation, err = pe.ReadUint16(off); err != nil {
return rows, n, err
}
off += 2
n += 2
if indexSize, err = pe.readFromMetadataStream(idxString, off, &rows[i].Name); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
if indexSize, err = pe.readFromMetadataStream(idxGUID, off, &rows[i].Mvid); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
if indexSize, err = pe.readFromMetadataStream(idxGUID, off, &rows[i].EncID); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
if indexSize, err = pe.readFromMetadataStream(idxGUID, off, &rows[i].EncBaseID); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
}
return rows, n, nil
}
// TypeRef 0x01
type TypeRefTableRow struct {
// an index into a Module, ModuleRef, AssemblyRef or TypeRef table, or null;
// more precisely, a ResolutionScope (§II.24.2.6) coded index.
ResolutionScope uint32 `json:"resolution_scope"`
// an index into the String heap
TypeName uint32 `json:"type_name"`
// an index into the String heap
TypeNamespace uint32 `json:"type_namespace"`
}
// TypeRef 0x01
func (pe *File) parseMetadataTypeRefTable(off uint32) ([]TypeRefTableRow, uint32, error) {
var err error
var indexSize uint32
var n uint32
rowCount := int(pe.CLR.MetadataTables[TypeRef].CountCols)
rows := make([]TypeRefTableRow, rowCount)
for i := 0; i < rowCount; i++ {
if indexSize, err = pe.readFromMetadataStream(idxResolutionScope, off, &rows[i].ResolutionScope); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
if indexSize, err = pe.readFromMetadataStream(idxString, off, &rows[i].TypeName); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
if indexSize, err = pe.readFromMetadataStream(idxString, off, &rows[i].TypeNamespace); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
}
return rows, n, nil
}
// TypeDef 0x02
type TypeDefTableRow struct {
// a 4-byte bitmask of type TypeAttributes, §II.23.1.15
Flags uint32 `json:"flags"`
// an index into the String heap
TypeName uint32 `json:"type_name"`
// an index into the String heap
TypeNamespace uint32 `json:"type_namespace"`
// an index into the TypeDef, TypeRef, or TypeSpec table; more precisely,
// a TypeDefOrRef (§II.24.2.6) coded index
Extends uint32 `json:"extends"`
// an index into the Field table; it marks the first of a contiguous run
// of Fields owned by this Type
FieldList uint32 `json:"field_list"`
// an index into the MethodDef table; it marks the first of a contiguous
// run of Methods owned by this Type
MethodList uint32 `json:"method_list"`
}
// TypeDef 0x02
func (pe *File) parseMetadataTypeDefTable(off uint32) ([]TypeDefTableRow, uint32, error) {
var err error
var indexSize uint32
var n uint32
rowCount := int(pe.CLR.MetadataTables[TypeDef].CountCols)
rows := make([]TypeDefTableRow, rowCount)
for i := 0; i < rowCount; i++ {
if rows[i].Flags, err = pe.ReadUint32(off); err != nil {
return rows, n, err
}
off += 4
n += 4
if indexSize, err = pe.readFromMetadataStream(idxString, off, &rows[i].TypeName); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
if indexSize, err = pe.readFromMetadataStream(idxString, off, &rows[i].TypeNamespace); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
if indexSize, err = pe.readFromMetadataStream(idxTypeDefOrRef, off, &rows[i].Extends); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
if indexSize, err = pe.readFromMetadataStream(idxField, off, &rows[i].FieldList); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
if indexSize, err = pe.readFromMetadataStream(idxMethodDef, off, &rows[i].MethodList); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
}
return rows, n, nil
}
// Field 0x04
type FieldTableRow struct {
// a 2-byte bitmask of type FieldAttributes, §II.23.1.5
Flags uint16 `json:"flags"`
// an index into the String heap
Name uint32 `json:"name"`
// an index into the Blob heap
Signature uint32 `json:"signature"`
}
// Field 0x04
func (pe *File) parseMetadataFieldTable(off uint32) ([]FieldTableRow, uint32, error) {
var err error
var indexSize uint32
var n uint32
rowCount := int(pe.CLR.MetadataTables[Field].CountCols)
rows := make([]FieldTableRow, rowCount)
for i := 0; i < rowCount; i++ {
if rows[i].Flags, err = pe.ReadUint16(off); err != nil {
return rows, n, err
}
off += 2
n += 2
if indexSize, err = pe.readFromMetadataStream(idxString, off, &rows[i].Name); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
if indexSize, err = pe.readFromMetadataStream(idxBlob, off, &rows[i].Signature); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
}
return rows, n, nil
}
// MethodDef 0x06
type MethodDefTableRow struct {
// a 4-byte constant
RVA uint32 `json:"rva"`
// a 2-byte bitmask of type MethodImplAttributes, §II.23.1.10
ImplFlags uint16 `json:"impl_flags"`
// a 2-byte bitmask of type MethodAttributes, §II.23.1.10
Flags uint16 `json:"flags"`
// an index into the String heap
Name uint32 `json:"name"`
// an index into the Blob heap
Signature uint32 `json:"signature"`
// an index into the Param table
ParamList uint32 `json:"param_list"`
}
// MethodDef 0x06
func (pe *File) parseMetadataMethodDefTable(off uint32) ([]MethodDefTableRow, uint32, error) {
var err error
var indexSize uint32
var n uint32
rowCount := int(pe.CLR.MetadataTables[MethodDef].CountCols)
rows := make([]MethodDefTableRow, rowCount)
for i := 0; i < rowCount; i++ {
if rows[i].RVA, err = pe.ReadUint32(off); err != nil {
return rows, n, err
}
off += 4
n += 4
if rows[i].ImplFlags, err = pe.ReadUint16(off); err != nil {
return rows, n, err
}
off += 2
n += 2
if rows[i].Flags, err = pe.ReadUint16(off); err != nil {
return rows, n, err
}
off += 2
n += 2
if indexSize, err = pe.readFromMetadataStream(idxString, off, &rows[i].Name); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
if indexSize, err = pe.readFromMetadataStream(idxBlob, off, &rows[i].Signature); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
if indexSize, err = pe.readFromMetadataStream(idxParam, off, &rows[i].ParamList); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
}
return rows, n, nil
}
// Param 0x08
type ParamTableRow struct {
// a 2-byte bitmask of type ParamAttributes, §II.23.1.13
Flags uint16 `json:"flags"`
// a 2-byte constant
Sequence uint16 `json:"sequence"`
// an index into the String heap
Name uint32 `json:"name"`
}
// Param 0x08
func (pe *File) parseMetadataParamTable(off uint32) ([]ParamTableRow, uint32, error) {
var err error
var indexSize uint32
var n uint32
rowCount := int(pe.CLR.MetadataTables[Param].CountCols)
rows := make([]ParamTableRow, rowCount)
for i := 0; i < rowCount; i++ {
if rows[i].Flags, err = pe.ReadUint16(off); err != nil {
return rows, n, err
}
off += 2
n += 2
if rows[i].Sequence, err = pe.ReadUint16(off); err != nil {
return rows, n, err
}
off += 2
n += 2
if indexSize, err = pe.readFromMetadataStream(idxString, off, &rows[i].Name); err != nil {
return rows, n, err
}
off += indexSize
n += indexSize
}
return rows, n, nil
}
// InterfaceImpl 0x09
type InterfaceImplTableRow struct {
// an index into the TypeDef table
Class uint32 `json:"class"`
// an index into the TypeDef, TypeRef, or TypeSpec table; more precisely,
// a TypeDefOrRef (§II.24.2.6) coded index
Interface uint32 `json:"interface"`
}
// InterfaceImpl 0x09
func (pe *File) parseMetadataInterfaceImplTable(off uint32) ([]InterfaceImplTableRow, uint32, error) {
var err error
var indexSize uint32
var n uint32
rowCount := int(pe.CLR.MetadataTables[InterfaceImpl].CountCols)
rows := make([]InterfaceImplTableRow, rowCount)
for i := 0; i < rowCount; i++ {
if
gitextract_so1rfj4w/ ├── .editorconfig ├── .gitattributes ├── .github/ │ ├── FUNDING.YML │ └── workflows/ │ └── ci.yaml ├── .gitignore ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── LICENSE ├── README.md ├── anomaly.go ├── anomaly_test.go ├── arch.go ├── boundimports.go ├── boundimports_test.go ├── cmd/ │ ├── dump.go │ ├── main.go │ ├── size.go │ └── size_test.go ├── debug.go ├── debug_test.go ├── delayimports.go ├── delayimports_test.go ├── dosheader.go ├── dosheader_test.go ├── dotnet.go ├── dotnet_helper.go ├── dotnet_metadata_tables.go ├── dotnet_test.go ├── exception.go ├── exception_test.go ├── exports.go ├── exports_test.go ├── file.go ├── file_test.go ├── globalptr.go ├── go.mod ├── go.sum ├── helper.go ├── helper_test.go ├── iat.go ├── imports.go ├── imports_test.go ├── loadconfig.go ├── loadconfig_test.go ├── log/ │ ├── README.md │ ├── filter.go │ ├── filter_test.go │ ├── global.go │ ├── global_test.go │ ├── helper.go │ ├── helper_test.go │ ├── level.go │ ├── level_test.go │ ├── log.go │ ├── log_test.go │ ├── std.go │ ├── std_test.go │ ├── value.go │ └── value_test.go ├── ntheader.go ├── ntheader_test.go ├── ordlookup.go ├── overlay.go ├── overlay_test.go ├── pe.go ├── reloc.go ├── reloc_test.go ├── resource.go ├── resource_test.go ├── richheader.go ├── richheader_test.go ├── scripts/ │ ├── extract-rsrc-lang.py │ └── ms-lcid.txt ├── section.go ├── section_test.go ├── security.go ├── security_linux_mac.go ├── security_test.go ├── security_windows.go ├── staticcheck.conf ├── symbol.go ├── symbol_test.go ├── test/ │ ├── WdBoot.sys │ ├── acpi.sys │ ├── amdi2c.sys │ ├── amdxata.sys │ └── look ├── tls.go ├── tls_test.go ├── version.go └── version_test.go
SYMBOL INDEX (1452 symbols across 72 files)
FILE: anomaly.go
method GetAnomalies (line 91) | func (pe *File) GetAnomalies() error {
method addAnomaly (line 214) | func (pe *File) addAnomaly(anomaly string) {
FILE: anomaly_test.go
function TestGetAnomalies (line 11) | func TestGetAnomalies(t *testing.T) {
FILE: arch.go
method parseArchitectureDirectory (line 9) | func (pe *File) parseArchitectureDirectory(rva, size uint32) error {
FILE: boundimports.go
constant MaxStringLength (line 15) | MaxStringLength = uint32(0x100)
type ImageBoundImportDescriptor (line 19) | type ImageBoundImportDescriptor struct
type ImageBoundForwardedRef (line 31) | type ImageBoundForwardedRef struct
type BoundImportDescriptorData (line 38) | type BoundImportDescriptorData struct
type BoundForwardedRefData (line 45) | type BoundForwardedRefData struct
method parseBoundImportDirectory (line 56) | func (pe *File) parseBoundImportDirectory(rva, size uint32) (err error) {
FILE: boundimports_test.go
type TestBoundImportEntry (line 12) | type TestBoundImportEntry struct
function TestBoundImportDirectory (line 19) | func TestBoundImportDirectory(t *testing.T) {
FILE: cmd/dump.go
function loopFilesWorker (line 32) | func loopFilesWorker(cfg config) error {
function LoopDirsFiles (line 51) | func LoopDirsFiles(path string) error {
function prettyPrint (line 69) | func prettyPrint(iface interface{}) string {
function humanizeTimestamp (line 81) | func humanizeTimestamp(ts uint32) string {
function hexDump (line 86) | func hexDump(b []byte) {
function hexDumpSize (line 114) | func hexDumpSize(b []byte, size int) {
function IntToByteArray (line 151) | func IntToByteArray(num uint64) []byte {
function sentenceCase (line 161) | func sentenceCase(s string) string {
function isDirectory (line 186) | func isDirectory(path string) bool {
function parse (line 194) | func parse(filePath string, cfg config) {
function parsePE (line 217) | func parsePE(filename string, cfg config) {
FILE: cmd/main.go
type config (line 14) | type config struct
function main (line 36) | func main() {
function showHelp (line 129) | func showHelp() {
FILE: cmd/size.go
constant KB (line 13) | KB = 1000
constant MB (line 14) | MB = 1000 * KB
constant GB (line 15) | GB = 1000 * MB
constant TB (line 16) | TB = 1000 * GB
constant PB (line 17) | PB = 1000 * TB
constant KiB (line 21) | KiB = 1024
constant MiB (line 22) | MiB = 1024 * KiB
constant GiB (line 23) | GiB = 1024 * MiB
constant TiB (line 24) | TiB = 1024 * GiB
constant PiB (line 25) | PiB = 1024 * TiB
type unitMap (line 28) | type unitMap
function getSizeAndUnit (line 40) | func getSizeAndUnit(size float64, base float64, _map []string) (float64,...
function CustomSize (line 52) | func CustomSize(format string, size float64, base float64, _map []string...
function HumanSizeWithPrecision (line 59) | func HumanSizeWithPrecision(size float64, precision int) string {
function HumanSize (line 66) | func HumanSize(size float64) string {
function BytesSize (line 72) | func BytesSize(size float64) string {
function FromHumanSize (line 78) | func FromHumanSize(size string) (int64, error) {
function RAMInBytes (line 86) | func RAMInBytes(size string) (int64, error) {
function parseSize (line 91) | func parseSize(sizeStr string, uMap unitMap) (int64, error) {
FILE: cmd/size_test.go
function ExampleBytesSize (line 11) | func ExampleBytesSize() {
function ExampleHumanSize (line 21) | func ExampleHumanSize() {
function ExampleFromHumanSize (line 32) | func ExampleFromHumanSize() {
function ExampleRAMInBytes (line 46) | func ExampleRAMInBytes() {
function TestBytesSize (line 62) | func TestBytesSize(t *testing.T) {
function TestHumanSize (line 73) | func TestHumanSize(t *testing.T) {
function TestFromHumanSize (line 85) | func TestFromHumanSize(t *testing.T) {
function TestRAMInBytes (line 163) | func TestRAMInBytes(t *testing.T) {
function BenchmarkParseSize (line 194) | func BenchmarkParseSize(b *testing.B) {
function assertEquals (line 206) | func assertEquals(t *testing.T, expected, actual interface{}) {
type parseFn (line 214) | type parseFn
method String (line 217) | func (fn parseFn) String() string {
function assertSuccessEquals (line 222) | func assertSuccessEquals(t *testing.T, expected int64, fn parseFn, arg s...
function assertError (line 230) | func assertError(t *testing.T, fn parseFn, arg string) {
FILE: debug.go
constant ImageDebugTypeUnknown (line 16) | ImageDebugTypeUnknown = 0
constant ImageDebugTypeCOFF (line 20) | ImageDebugTypeCOFF = 1
constant ImageDebugTypeCodeView (line 23) | ImageDebugTypeCodeView = 2
constant ImageDebugTypeFPO (line 28) | ImageDebugTypeFPO = 3
constant ImageDebugTypeMisc (line 31) | ImageDebugTypeMisc = 4
constant ImageDebugTypeException (line 34) | ImageDebugTypeException = 5
constant ImageDebugTypeFixup (line 37) | ImageDebugTypeFixup = 6
constant ImageDebugTypeOMAPToSrc (line 40) | ImageDebugTypeOMAPToSrc = 7
constant ImageDebugTypeOMAPFromSrc (line 43) | ImageDebugTypeOMAPFromSrc = 8
constant ImageDebugTypeBorland (line 46) | ImageDebugTypeBorland = 9
constant ImageDebugTypeReserved (line 49) | ImageDebugTypeReserved = 10
constant ImageDebugTypeCLSID (line 52) | ImageDebugTypeCLSID = 11
constant ImageDebugTypeVCFeature (line 55) | ImageDebugTypeVCFeature = 12
constant ImageDebugTypePOGO (line 58) | ImageDebugTypePOGO = 13
constant ImageDebugTypeILTCG (line 61) | ImageDebugTypeILTCG = 14
constant ImageDebugTypeMPX (line 64) | ImageDebugTypeMPX = 15
constant ImageDebugTypeRepro (line 67) | ImageDebugTypeRepro = 16
constant ImageDebugTypeExDllCharacteristics (line 70) | ImageDebugTypeExDllCharacteristics = 20
constant CVSignatureRSDS (line 75) | CVSignatureRSDS = 0x53445352
constant CVSignatureNB10 (line 78) | CVSignatureNB10 = 0x3031424e
constant FrameFPO (line 83) | FrameFPO = 0x0
constant FrameTrap (line 86) | FrameTrap = 0x1
constant FrameTSS (line 89) | FrameTSS = 0x2
constant FrameNonFPO (line 92) | FrameNonFPO = 0x3
type DllCharacteristicsExType (line 96) | type DllCharacteristicsExType
method String (line 760) | func (flag DllCharacteristicsExType) String() string {
constant ImageDllCharacteristicsExCETCompat (line 101) | ImageDllCharacteristicsExCETCompat = 0x0001
constant POGOTypePGU (line 106) | POGOTypePGU = 0x50475500
constant POGOTypePGI (line 108) | POGOTypePGI = 0x50474900
constant POGOTypePGO (line 110) | POGOTypePGO = 0x50474F00
constant POGOTypeLTCG (line 112) | POGOTypeLTCG = 0x4c544347
type ImageDebugDirectoryType (line 116) | type ImageDebugDirectoryType
method String (line 697) | func (t ImageDebugDirectoryType) String() string {
type ImageDebugDirectory (line 122) | type ImageDebugDirectory struct
type DebugEntry (line 150) | type DebugEntry struct
type GUID (line 164) | type GUID struct
method String (line 692) | func (g GUID) String() string {
type CVSignature (line 172) | type CVSignature
method String (line 745) | func (s CVSignature) String() string {
type CVInfoPDB70 (line 175) | type CVInfoPDB70 struct
type CVHeader (line 192) | type CVHeader struct
type CVInfoPDB20 (line 202) | type CVInfoPDB20 struct
type FPOFrameType (line 219) | type FPOFrameType
method String (line 675) | func (ft FPOFrameType) String() string {
type FPOData (line 224) | type FPOData struct
type ImagePGOItem (line 257) | type ImagePGOItem struct
type POGOType (line 264) | type POGOType
method String (line 728) | func (p POGOType) String() string {
type POGO (line 269) | type POGO struct
type VCFeature (line 275) | type VCFeature struct
type REPRO (line 283) | type REPRO struct
type ImageDebugMisc (line 289) | type ImageDebugMisc struct
method parseDebugDirectory (line 313) | func (pe *File) parseDebugDirectory(rva, size uint32) error {
function SectionAttributeDescription (line 563) | func SectionAttributeDescription(section string) string {
FILE: debug_test.go
type TestDebugIn (line 12) | type TestDebugIn struct
function TestDebugDirectoryCodeView (line 17) | func TestDebugDirectoryCodeView(t *testing.T) {
function TestDebugDirectoryPOGO (line 148) | func TestDebugDirectoryPOGO(t *testing.T) {
function TestDebugDirectoryREPRO (line 258) | func TestDebugDirectoryREPRO(t *testing.T) {
function TestDebugDirectoryExDLLCharacteristics (line 342) | func TestDebugDirectoryExDLLCharacteristics(t *testing.T) {
function TestDebugDirectoryVCFeature (line 426) | func TestDebugDirectoryVCFeature(t *testing.T) {
function TestDebugDirectoryFPO (line 509) | func TestDebugDirectoryFPO(t *testing.T) {
function TestDebugSectionAttributes (line 652) | func TestDebugSectionAttributes(t *testing.T) {
FILE: delayimports.go
type ImageDelayImportDescriptor (line 12) | type ImageDelayImportDescriptor struct
type DelayImport (line 58) | type DelayImport struct
method parseDelayImportDirectory (line 69) | func (pe *File) parseDelayImportDirectory(rva, size uint32) error {
method GetDelayImportEntryInfoByRVA (line 145) | func (pe *File) GetDelayImportEntryInfoByRVA(rva uint32) (DelayImport, i...
FILE: delayimports_test.go
type TestDelayImportEntry (line 12) | type TestDelayImportEntry struct
function TestDelayImportDirectory (line 18) | func TestDelayImportDirectory(t *testing.T) {
FILE: dosheader.go
type ImageDOSHeader (line 12) | type ImageDOSHeader struct
method ParseDOSHeader (line 76) | func (pe *File) ParseDOSHeader() (err error) {
FILE: dosheader_test.go
type TestDOSHeader (line 11) | type TestDOSHeader struct
function TestParseDOSHeader (line 15) | func TestParseDOSHeader(t *testing.T) {
function TestParseDOSHeaderNonMZ (line 71) | func TestParseDOSHeaderNonMZ(t *testing.T) {
FILE: dotnet.go
type COMImageFlagsType (line 15) | type COMImageFlagsType
method String (line 754) | func (flags COMImageFlagsType) String() []string {
constant COMImageFlagsILOnly (line 22) | COMImageFlagsILOnly = 0x00000001
constant COMImageFlags32BitRequired (line 25) | COMImageFlags32BitRequired = 0x00000002
constant COMImageFlagILLibrary (line 30) | COMImageFlagILLibrary = 0x00000004
constant COMImageFlagsStrongNameSigned (line 33) | COMImageFlagsStrongNameSigned = 0x00000008
constant COMImageFlagsNativeEntrypoint (line 38) | COMImageFlagsNativeEntrypoint = 0x00000010
constant COMImageFlagsTrackDebugData (line 42) | COMImageFlagsTrackDebugData = 0x00010000
constant COMImageFlags32BitPreferred (line 49) | COMImageFlags32BitPreferred = 0x00020000
constant CORVTable32Bit (line 55) | CORVTable32Bit = 0x01
constant CORVTable64Bit (line 58) | CORVTable64Bit = 0x02
constant CORVTableFromUnmanaged (line 62) | CORVTableFromUnmanaged = 0x04
constant CORVTableFromUnmanagedRetainAppDomain (line 67) | CORVTableFromUnmanagedRetainAppDomain = 0x08
constant CORVTableCallMostDerived (line 70) | CORVTableCallMostDerived = 0x10
constant Module (line 76) | Module = 0
constant TypeRef (line 78) | TypeRef = 1
constant TypeDef (line 80) | TypeDef = 2
constant FieldPtr (line 83) | FieldPtr = 3
constant Field (line 85) | Field = 4
constant MethodPtr (line 88) | MethodPtr = 5
constant MethodDef (line 90) | MethodDef = 6
constant ParamPtr (line 93) | ParamPtr = 7
constant Param (line 95) | Param = 8
constant InterfaceImpl (line 97) | InterfaceImpl = 9
constant MemberRef (line 99) | MemberRef = 10
constant Constant (line 102) | Constant = 11
constant CustomAttribute (line 104) | CustomAttribute = 12
constant FieldMarshal (line 107) | FieldMarshal = 13
constant DeclSecurity (line 109) | DeclSecurity = 14
constant ClassLayout (line 112) | ClassLayout = 15
constant FieldLayout (line 115) | FieldLayout = 16
constant StandAloneSig (line 119) | StandAloneSig = 17
constant EventMap (line 122) | EventMap = 18
constant EventPtr (line 125) | EventPtr = 19
constant Event (line 127) | Event = 20
constant PropertyMap (line 130) | PropertyMap = 21
constant PropertyPtr (line 133) | PropertyPtr = 22
constant Property (line 135) | Property = 23
constant MethodSemantics (line 138) | MethodSemantics = 24
constant MethodImpl (line 140) | MethodImpl = 25
constant ModuleRef (line 142) | ModuleRef = 26
constant TypeSpec (line 144) | TypeSpec = 27
constant ImplMap (line 147) | ImplMap = 28
constant FieldRVA (line 149) | FieldRVA = 29
constant ENCLog (line 153) | ENCLog = 30
constant ENCMap (line 156) | ENCMap = 31
constant Assembly (line 159) | Assembly = 32
constant AssemblyProcessor (line 161) | AssemblyProcessor = 33
constant AssemblyOS (line 163) | AssemblyOS = 34
constant AssemblyRef (line 165) | AssemblyRef = 35
constant AssemblyRefProcessor (line 167) | AssemblyRefProcessor = 36
constant AssemblyRefOS (line 169) | AssemblyRefOS = 37
constant FileMD (line 172) | FileMD = 38
constant ExportedType (line 177) | ExportedType = 39
constant ManifestResource (line 179) | ManifestResource = 40
constant NestedClass (line 182) | NestedClass = 41
constant GenericParam (line 185) | GenericParam = 42
constant MethodSpec (line 187) | MethodSpec = 43
constant GenericParamConstraint (line 190) | GenericParamConstraint = 44
constant StringStream (line 195) | StringStream = 0
constant GUIDStream (line 196) | GUIDStream = 1
constant BlobStream (line 197) | BlobStream = 2
function MetadataTableIndexToString (line 202) | func MetadataTableIndexToString(k int) string {
method GetMetadataStreamIndexSize (line 259) | func (pe *File) GetMetadataStreamIndexSize(BitPosition int) int {
type ImageDataDirectory (line 275) | type ImageDataDirectory struct
type ImageCOR20Header (line 285) | type ImageCOR20Header struct
type ImageCORVTableFixup (line 362) | type ImageCORVTableFixup struct
type MetadataHeader (line 369) | type MetadataHeader struct
type MetadataStreamHeader (line 406) | type MetadataStreamHeader struct
type MetadataTableStreamHeader (line 421) | type MetadataTableStreamHeader struct
type MetadataTable (line 457) | type MetadataTable struct
type CLRData (line 471) | type CLRData struct
method parseMetadataStream (line 483) | func (pe *File) parseMetadataStream(off, size uint32) (MetadataTableStre...
method parseMetadataHeader (line 498) | func (pe *File) parseMetadataHeader(offset, size uint32) (MetadataHeader...
method parseCLRHeaderDirectory (line 539) | func (pe *File) parseCLRHeaderDirectory(rva, size uint32) error {
FILE: dotnet_helper.go
constant idxStringStream (line 10) | idxStringStream = iota + 100
constant idxGUIDStream (line 11) | idxGUIDStream
constant idxBlobStream (line 12) | idxBlobStream
type codedidx (line 15) | type codedidx struct
method getCodedIndexSize (line 49) | func (pe *File) getCodedIndexSize(tagbits uint32, idx ...int) uint32 {
method readFromMetadataStream (line 77) | func (pe *File) readFromMetadataStream(cidx codedidx, off uint32, out *u...
FILE: dotnet_metadata_tables.go
type ModuleTableRow (line 11) | type ModuleTableRow struct
method parseMetadataModuleTable (line 26) | func (pe *File) parseMetadataModuleTable(off uint32) ([]ModuleTableRow, ...
type TypeRefTableRow (line 68) | type TypeRefTableRow struct
method parseMetadataTypeRefTable (line 79) | func (pe *File) parseMetadataTypeRefTable(off uint32) ([]TypeRefTableRow...
type TypeDefTableRow (line 109) | type TypeDefTableRow struct
method parseMetadataTypeDefTable (line 128) | func (pe *File) parseMetadataTypeDefTable(off uint32) ([]TypeDefTableRow...
type FieldTableRow (line 176) | type FieldTableRow struct
method parseMetadataFieldTable (line 186) | func (pe *File) parseMetadataFieldTable(off uint32) ([]FieldTableRow, ui...
type MethodDefTableRow (line 216) | type MethodDefTableRow struct
method parseMetadataMethodDefTable (line 232) | func (pe *File) parseMetadataMethodDefTable(off uint32) ([]MethodDefTabl...
type ParamTableRow (line 280) | type ParamTableRow struct
method parseMetadataParamTable (line 290) | func (pe *File) parseMetadataParamTable(off uint32) ([]ParamTableRow, ui...
type InterfaceImplTableRow (line 320) | type InterfaceImplTableRow struct
method parseMetadataInterfaceImplTable (line 329) | func (pe *File) parseMetadataInterfaceImplTable(off uint32) ([]Interface...
type MemberRefTableRow (line 353) | type MemberRefTableRow struct
method parseMetadataMemberRefTable (line 364) | func (pe *File) parseMetadataMemberRefTable(off uint32) ([]MemberRefTabl...
type ConstantTableRow (line 395) | type ConstantTableRow struct
method parseMetadataConstantTable (line 409) | func (pe *File) parseMetadataConstantTable(off uint32) ([]ConstantTableR...
type CustomAttributeTableRow (line 445) | type CustomAttributeTableRow struct
method parseMetadataCustomAttributeTable (line 457) | func (pe *File) parseMetadataCustomAttributeTable(off uint32) ([]CustomA...
type FieldMarshalTableRow (line 487) | type FieldMarshalTableRow struct
method parseMetadataFieldMarshalTable (line 496) | func (pe *File) parseMetadataFieldMarshalTable(off uint32) ([]FieldMarsh...
type DeclSecurityTableRow (line 520) | type DeclSecurityTableRow struct
method parseMetadataDeclSecurityTable (line 531) | func (pe *File) parseMetadataDeclSecurityTable(off uint32) ([]DeclSecuri...
type ClassLayoutTableRow (line 561) | type ClassLayoutTableRow struct
method parseMetadataClassLayoutTable (line 571) | func (pe *File) parseMetadataClassLayoutTable(off uint32) ([]ClassLayout...
type FieldLayoutTableRow (line 601) | type FieldLayoutTableRow struct
method parseMetadataFieldLayoutTable (line 607) | func (pe *File) parseMetadataFieldLayoutTable(off uint32) ([]FieldLayout...
type StandAloneSigTableRow (line 631) | type StandAloneSigTableRow struct
method parseMetadataStandAloneSignTable (line 636) | func (pe *File) parseMetadataStandAloneSignTable(off uint32) ([]StandAlo...
type EventMapTableRow (line 654) | type EventMapTableRow struct
method parseMetadataEventMapTable (line 662) | func (pe *File) parseMetadataEventMapTable(off uint32) ([]EventMapTableR...
type EventTableRow (line 687) | type EventTableRow struct
method parseMetadataEventTable (line 698) | func (pe *File) parseMetadataEventTable(off uint32) ([]EventTableRow, ui...
type PropertyMapTableRow (line 728) | type PropertyMapTableRow struct
method parseMetadataPropertyMapTable (line 736) | func (pe *File) parseMetadataPropertyMapTable(off uint32) ([]PropertyMap...
type PropertyTableRow (line 760) | type PropertyTableRow struct
method parseMetadataPropertyTable (line 770) | func (pe *File) parseMetadataPropertyTable(off uint32) ([]PropertyTableR...
type MethodSemanticsTableRow (line 800) | type MethodSemanticsTableRow struct
method parseMetadataMethodSemanticsTable (line 811) | func (pe *File) parseMetadataMethodSemanticsTable(off uint32) ([]MethodS...
type MethodImplTableRow (line 841) | type MethodImplTableRow struct
method parseMetadataMethodImplTable (line 853) | func (pe *File) parseMetadataMethodImplTable(off uint32) ([]MethodImplTa...
type ModuleRefTableRow (line 883) | type ModuleRefTableRow struct
method parseMetadataModuleRefTable (line 889) | func (pe *File) parseMetadataModuleRefTable(off uint32) ([]ModuleRefTabl...
type TypeSpecTableRow (line 907) | type TypeSpecTableRow struct
method parseMetadataTypeSpecTable (line 913) | func (pe *File) parseMetadataTypeSpecTable(off uint32) ([]TypeSpecTableR...
type ImplMapTableRow (line 931) | type ImplMapTableRow struct
method parseMetadataImplMapTable (line 944) | func (pe *File) parseMetadataImplMapTable(off uint32) ([]ImplMapTableRow...
type FieldRVATableRow (line 980) | type FieldRVATableRow struct
method parseMetadataFieldRVATable (line 988) | func (pe *File) parseMetadataFieldRVATable(off uint32) ([]FieldRVATableR...
type AssemblyTableRow (line 1012) | type AssemblyTableRow struct
method parseMetadataAssemblyTable (line 1034) | func (pe *File) parseMetadataAssemblyTable(off uint32) ([]AssemblyTableR...
type AssemblyProcessorTableRow (line 1100) | type AssemblyProcessorTableRow struct
type AssemblyOSTableRow (line 1105) | type AssemblyOSTableRow struct
type AssemblyRefTableRow (line 1112) | type AssemblyRefTableRow struct
method parseMetadataAssemblyRefTable (line 1125) | func (pe *File) parseMetadataAssemblyRefTable(off uint32) ([]AssemblyRef...
type AssemblyRefProcessorTableRow (line 1191) | type AssemblyRefProcessorTableRow struct
type AssemblyRefOSTableRow (line 1197) | type AssemblyRefOSTableRow struct
type ExportedTypeTableRow (line 1205) | type ExportedTypeTableRow struct
method parseMetadataExportedTypeTable (line 1214) | func (pe *File) parseMetadataExportedTypeTable(off uint32) ([]ExportedTy...
type ManifestResourceTableRow (line 1256) | type ManifestResourceTableRow struct
method parseMetadataManifestResourceTable (line 1264) | func (pe *File) parseMetadataManifestResourceTable(off uint32) ([]Manife...
type NestedClassTableRow (line 1300) | type NestedClassTableRow struct
method parseMetadataNestedClassTable (line 1306) | func (pe *File) parseMetadataNestedClassTable(off uint32) ([]NestedClass...
type GenericParamTableRow (line 1330) | type GenericParamTableRow struct
method parseMetadataGenericParamTable (line 1338) | func (pe *File) parseMetadataGenericParamTable(off uint32) ([]GenericPar...
type MethodSpecTableRow (line 1373) | type MethodSpecTableRow struct
method parseMetadataMethodSpecTable (line 1379) | func (pe *File) parseMetadataMethodSpecTable(off uint32) ([]MethodSpecTa...
type GenericParamConstraintTableRow (line 1403) | type GenericParamConstraintTableRow struct
method parseMetadataGenericParamConstraintTable (line 1409) | func (pe *File) parseMetadataGenericParamConstraintTable(off uint32) ([]...
type FileTableRow (line 1433) | type FileTableRow struct
method parseMetadataFileTable (line 1440) | func (pe *File) parseMetadataFileTable(off uint32) ([]FileTableRow, uint...
FILE: dotnet_test.go
function TestClrDirectoryHeaders (line 14) | func TestClrDirectoryHeaders(t *testing.T) {
function TestClrDirectoryMetadataTables (line 144) | func TestClrDirectoryMetadataTables(t *testing.T) {
function TestClrDirectorCOMImageFlagsType (line 841) | func TestClrDirectorCOMImageFlagsType(t *testing.T) {
function TestClrDirectoryMalformed (line 865) | func TestClrDirectoryMalformed(t *testing.T) {
FILE: exception.go
constant UnwFlagNHandler (line 16) | UnwFlagNHandler = uint8(0x0)
constant UnwFlagEHandler (line 20) | UnwFlagEHandler = uint8(0x1)
constant UnwFlagUHandler (line 24) | UnwFlagUHandler = uint8(0x2)
constant UnwFlagChainInfo (line 33) | UnwFlagChainInfo = uint8(0x4)
constant rax (line 39) | rax = iota
constant rcx (line 40) | rcx
constant rdx (line 41) | rdx
constant rbx (line 42) | rbx
constant rsp (line 43) | rsp
constant rbp (line 44) | rbp
constant rsi (line 45) | rsi
constant rdi (line 46) | rdi
constant r8 (line 47) | r8
constant r9 (line 48) | r9
constant r10 (line 49) | r10
constant r11 (line 50) | r11
constant r12 (line 51) | r12
constant r13 (line 52) | r13
constant r14 (line 53) | r14
constant r15 (line 54) | r15
type UnwindOpType (line 78) | type UnwindOpType
method String (line 576) | func (uo UnwindOpType) String() string {
constant UwOpPushNonVol (line 87) | UwOpPushNonVol = UnwindOpType(0)
constant UwOpAllocLarge (line 95) | UwOpAllocLarge = UnwindOpType(1)
constant UwOpAllocSmall (line 100) | UwOpAllocSmall = UnwindOpType(2)
constant UwOpSetFpReg (line 109) | UwOpSetFpReg = UnwindOpType(3)
constant UwOpSaveNonVol (line 117) | UwOpSaveNonVol = UnwindOpType(4)
constant UwOpSaveNonVolFar (line 125) | UwOpSaveNonVolFar = UnwindOpType(5)
constant UwOpEpilog (line 133) | UwOpEpilog = UnwindOpType(6)
constant UwOpSpareCode (line 141) | UwOpSpareCode = UnwindOpType(7)
constant UwOpSaveXmm128 (line 146) | UwOpSaveXmm128 = UnwindOpType(8)
constant UwOpSaveXmm128Far (line 151) | UwOpSaveXmm128Far = UnwindOpType(9)
constant UwOpPushMachFrame (line 155) | UwOpPushMachFrame = UnwindOpType(10)
constant UwOpSetFpRegLarge (line 171) | UwOpSetFpRegLarge = UnwindOpType(11)
type ImageRuntimeFunctionEntry (line 178) | type ImageRuntimeFunctionEntry struct
type ImageARMRuntimeFunctionEntry (line 193) | type ImageARMRuntimeFunctionEntry struct
type UnwindCode (line 238) | type UnwindCode struct
type UnwindInfo (line 258) | type UnwindInfo struct
type ScopeRecord (line 317) | type ScopeRecord struct
type ScopeTable (line 340) | type ScopeTable struct
type Exception (line 360) | type Exception struct
method parseUnwindCode (line 365) | func (pe *File) parseUnwindCode(offset uint32, version uint8) (UnwindCod...
method parseUnwindInfo (line 445) | func (pe *File) parseUnwindInfo(unwindInfo uint32) UnwindInfo {
method parseExceptionDirectory (line 521) | func (pe *File) parseExceptionDirectory(rva, size uint32) error {
function PrettyUnwindInfoHandlerFlags (line 557) | func PrettyUnwindInfoHandlerFlags(flags uint8) []string {
FILE: exception_test.go
type TestExceptionEntry (line 13) | type TestExceptionEntry struct
function TestParseExceptionDirectory (line 20) | func TestParseExceptionDirectory(t *testing.T) {
function TestExceptionDirectoryUnwindOpcode (line 121) | func TestExceptionDirectoryUnwindOpcode(t *testing.T) {
FILE: exports.go
constant maxExportedSymbols (line 14) | maxExportedSymbols = 0x2000
type ImageExportDirectory (line 27) | type ImageExportDirectory struct
type ExportFunction (line 69) | type ExportFunction struct
type Export (line 80) | type Export struct
method parseExportDirectory (line 101) | func (pe *File) parseExportDirectory(rva, size uint32) error {
method GetExportFunctionByRVA (line 322) | func (pe *File) GetExportFunctionByRVA(rva uint32) ExportFunction {
FILE: exports_test.go
type TestExport (line 11) | type TestExport struct
function TestExportDirectory (line 19) | func TestExportDirectory(t *testing.T) {
FILE: file.go
type File (line 17) | type File struct
method Close (line 199) | func (pe *File) Close() error {
method Unmap (line 209) | func (pe *File) Unmap() error {
method Parse (line 218) | func (pe *File) Parse() error {
method ParseDataDirectories (line 291) | func (pe *File) ParseDataDirectories() error {
type Options (line 49) | type Options struct
function New (line 121) | func New(name string, opts *Options) (*File, error) {
function NewFile (line 131) | func NewFile(f *os.File, opts *Options) (*File, error) {
function NewBytes (line 169) | func NewBytes(data []byte, opts *Options) (*File, error) {
method String (line 265) | func (entry ImageDirectoryEntry) String() string {
FILE: file_test.go
function TestParse (line 20) | func TestParse(t *testing.T) {
function TestParseOmitDirectories (line 36) | func TestParseOmitDirectories(t *testing.T) {
function TestNewBytes (line 56) | func TestNewBytes(t *testing.T) {
function TestChecksum (line 73) | func TestChecksum(t *testing.T) {
function TestCanParseWithHandleAndClose (line 107) | func TestCanParseWithHandleAndClose(t *testing.T) {
FILE: globalptr.go
constant AnoInvalidGlobalPtrReg (line 9) | AnoInvalidGlobalPtrReg = "Global pointer register offset outside of PE i...
method parseGlobalPtrDirectory (line 16) | func (pe *File) parseGlobalPtrDirectory(rva, size uint32) error {
FILE: helper.go
constant TinyPESize (line 20) | TinyPESize = 97
constant FileAlignmentHardcodedValue (line 26) | FileAlignmentHardcodedValue = 0x200
function Max (line 96) | func Max(x, y uint32) uint32 {
function min (line 103) | func min(a, b uint32) uint32 {
function Min (line 111) | func Min(values []uint32) uint32 {
function IsValidDosFilename (line 126) | func IsValidDosFilename(filename string) bool {
function IsValidFunctionName (line 142) | func IsValidFunctionName(functionName string) bool {
function IsPrintable (line 156) | func IsPrintable(s string) bool {
method getSectionByRva (line 171) | func (pe *File) getSectionByRva(rva uint32) *Section {
method getSectionNameByRva (line 181) | func (pe *File) getSectionNameByRva(rva uint32) string {
method getSectionByOffset (line 190) | func (pe *File) getSectionByOffset(offset uint32) *Section {
method GetOffsetFromRva (line 207) | func (pe *File) GetOffsetFromRva(rva uint32) uint32 {
method GetRVAFromOffset (line 224) | func (pe *File) GetRVAFromOffset(offset uint32) uint32 {
method getSectionByName (line 256) | func (pe *File) getSectionByName(secName string) (section *ImageSectionH...
method getStringAtRVA (line 267) | func (pe *File) getStringAtRVA(rva, maxLen uint32) string {
method readUnicodeStringAtRVA (line 289) | func (pe *File) readUnicodeStringAtRVA(rva uint32, maxLength uint32) str...
method readASCIIStringAtOffset (line 303) | func (pe *File) readASCIIStringAtOffset(offset, maxLength uint32) (uint3...
method GetStringFromData (line 318) | func (pe *File) GetStringFromData(offset uint32, data []byte) []byte {
method getStringAtOffset (line 340) | func (pe *File) getStringAtOffset(offset, size uint32) (string, error) {
method GetData (line 351) | func (pe *File) GetData(rva, length uint32) ([]byte, error) {
method adjustFileAlignment (line 389) | func (pe *File) adjustFileAlignment(va uint32) uint32 {
method adjustSectionAlignment (line 419) | func (pe *File) adjustSectionAlignment(va uint32) uint32 {
function alignDword (line 449) | func alignDword(offset, base uint32) uint32 {
function stringInSlice (line 454) | func stringInSlice(a string, list []string) bool {
function intInSlice (line 464) | func intInSlice(a uint32, list []uint32) bool {
method IsDriver (line 474) | func (pe *File) IsDriver() bool {
method IsDLL (line 531) | func (pe *File) IsDLL() bool {
method IsEXE (line 536) | func (pe *File) IsEXE() bool {
method Checksum (line 552) | func (pe *File) Checksum() uint32 {
method ReadUint64 (line 600) | func (pe *File) ReadUint64(offset uint32) (uint64, error) {
method ReadUint32 (line 609) | func (pe *File) ReadUint32(offset uint32) (uint32, error) {
method ReadUint16 (line 618) | func (pe *File) ReadUint16(offset uint32) (uint16, error) {
method ReadUint8 (line 627) | func (pe *File) ReadUint8(offset uint32) (uint8, error) {
method structUnpack (line 636) | func (pe *File) structUnpack(iface interface{}, offset, size uint32) (er...
method ReadBytesAtOffset (line 658) | func (pe *File) ReadBytesAtOffset(offset, size uint32) ([]byte, error) {
function DecodeUTF16String (line 675) | func DecodeUTF16String(b []byte) (string, error) {
function IsBitSet (line 689) | func IsBitSet(n uint64, pos int) bool {
function getAbsoluteFilePath (line 694) | func getAbsoluteFilePath(testfile string) string {
FILE: helper_test.go
function TestIsEXE (line 11) | func TestIsEXE(t *testing.T) {
function TestIsDLL (line 40) | func TestIsDLL(t *testing.T) {
function TestIsDriver (line 69) | func TestIsDriver(t *testing.T) {
FILE: iat.go
type IATEntry (line 8) | type IATEntry struct
method parseIATDirectory (line 28) | func (pe *File) parseIATDirectory(rva, size uint32) error {
FILE: imports.go
constant imageOrdinalFlag32 (line 18) | imageOrdinalFlag32 = uint32(0x80000000)
constant imageOrdinalFlag64 (line 19) | imageOrdinalFlag64 = uint64(0x8000000000000000)
constant maxRepeatedAddresses (line 20) | maxRepeatedAddresses = uint32(0xF)
constant maxAddressSpread (line 21) | maxAddressSpread = uint32(0x8000000)
constant addressMask32 (line 22) | addressMask32 = uint32(0x7fffffff)
constant addressMask64 (line 23) | addressMask64 = uint64(0x7fffffffffffffff)
constant maxDllLength (line 24) | maxDllLength = 0x200
constant maxImportNameLength (line 25) | maxImportNameLength = 0x200
type ImageImportDescriptor (line 55) | type ImageImportDescriptor struct
type ImageThunkData32 (line 85) | type ImageThunkData32 struct
type ImageThunkData64 (line 90) | type ImageThunkData64 struct
type ThunkData32 (line 94) | type ThunkData32 struct
type ThunkData64 (line 99) | type ThunkData64 struct
type ImportFunction (line 105) | type ImportFunction struct
type Import (line 137) | type Import struct
method parseImportDirectory (line 144) | func (pe *File) parseImportDirectory(rva, size uint32) (err error) {
method getImportTable32 (line 211) | func (pe *File) getImportTable32(rva uint32, maxLen uint32,
method getImportTable64 (line 336) | func (pe *File) getImportTable64(rva uint32, maxLen uint32,
method parseImports32 (line 463) | func (pe *File) parseImports32(importDesc interface{}, maxLen uint32) (
method parseImports64 (line 597) | func (pe *File) parseImports64(importDesc interface{}, maxLen uint32) ([...
method GetImportEntryInfoByRVA (line 733) | func (pe *File) GetImportEntryInfoByRVA(rva uint32) (Import, int) {
function md5hash (line 746) | func md5hash(text string) string {
method ImpHash (line 759) | func (pe *File) ImpHash() (string, error) {
FILE: imports_test.go
type TestImportEntry (line 12) | type TestImportEntry struct
function TestImportDirectory (line 18) | func TestImportDirectory(t *testing.T) {
function TestImpHash (line 130) | func TestImpHash(t *testing.T) {
FILE: loadconfig.go
type ImageGuardFlagType (line 25) | type ImageGuardFlagType
method String (line 1517) | func (flag ImageGuardFlagType) String() string {
constant ImageGuardFlagFIDSuppressed (line 31) | ImageGuardFlagFIDSuppressed = 0x1
constant ImageGuardFlagExportSuppressed (line 35) | ImageGuardFlagExportSuppressed = 0x2
constant ImageGuardCfInstrumented (line 43) | ImageGuardCfInstrumented = 0x00000100
constant ImageGuardCfWInstrumented (line 47) | ImageGuardCfWInstrumented = 0x00000200
constant ImageGuardCfFunctionTablePresent (line 51) | ImageGuardCfFunctionTablePresent = 0x00000400
constant ImageGuardSecurityCookieUnused (line 55) | ImageGuardSecurityCookieUnused = 0x00000800
constant ImageGuardProtectDelayLoadIAT (line 59) | ImageGuardProtectDelayLoadIAT = 0x00001000
constant ImageGuardDelayLoadIATInItsOwnSection (line 64) | ImageGuardDelayLoadIATInItsOwnSection = 0x00002000
constant ImageGuardCfExportSuppressionInfoPresent (line 69) | ImageGuardCfExportSuppressionInfoPresent = 0x00004000
constant ImageGuardCfEnableExportSuppression (line 73) | ImageGuardCfEnableExportSuppression = 0x00008000
constant ImageGuardCfLongJumpTablePresent (line 77) | ImageGuardCfLongJumpTablePresent = 0x00010000
constant ImageGuardCfFunctionTableSizeMask (line 84) | ImageGuardCfFunctionTableSizeMask = 0xF0000000
constant ImageGuardCfFunctionTableSizeShift (line 88) | ImageGuardCfFunctionTableSizeShift = 28
constant ImageDynamicRelocationGuardRfPrologue (line 92) | ImageDynamicRelocationGuardRfPrologue = 0x00000001
constant ImageDynamicRelocationGuardREpilogue (line 93) | ImageDynamicRelocationGuardREpilogue = 0x00000002
constant ImageEnclaveLongIDLength (line 98) | ImageEnclaveLongIDLength = 32
constant ImageEnclaveShortIDLength (line 99) | ImageEnclaveShortIDLength = 16
constant ImageEnclaveImportMatchNone (line 105) | ImageEnclaveImportMatchNone = 0x00000000
constant ImageEnclaveImportMatchUniqueID (line 110) | ImageEnclaveImportMatchUniqueID = 0x00000001
constant ImageEnclaveImportMatchAuthorID (line 117) | ImageEnclaveImportMatchAuthorID = 0x00000002
constant ImageEnclaveImportMatchFamilyID (line 122) | ImageEnclaveImportMatchFamilyID = 0x00000003
constant ImageEnclaveImportMatchImageID (line 127) | ImageEnclaveImportMatchImageID = 0x00000004
type ImageLoadConfigDirectory32 (line 131) | type ImageLoadConfigDirectory32 struct
type ImageLoadConfigDirectory64 (line 257) | type ImageLoadConfigDirectory64 struct
type ImageCHPEMetadataX86 (line 383) | type ImageCHPEMetadataX86 struct
type CodeRange (line 398) | type CodeRange struct
type CompilerIAT (line 404) | type CompilerIAT struct
type HybridPE (line 410) | type HybridPE struct
type ImageDynamicRelocationTable (line 417) | type ImageDynamicRelocationTable struct
type ImageDynamicRelocation32 (line 430) | type ImageDynamicRelocation32 struct
type ImageDynamicRelocation64 (line 442) | type ImageDynamicRelocation64 struct
type ImageDynamicRelocation32v2 (line 453) | type ImageDynamicRelocation32v2 struct
type ImageDynamicRelocation64v2 (line 463) | type ImageDynamicRelocation64v2 struct
type ImagePrologueDynamicRelocationHeader (line 473) | type ImagePrologueDynamicRelocationHeader struct
type ImageEpilogueDynamicRelocationHeader (line 478) | type ImageEpilogueDynamicRelocationHeader struct
type CFGFunction (line 487) | type CFGFunction struct
type CFGIATEntry (line 496) | type CFGIATEntry struct
type RelocBlock (line 503) | type RelocBlock struct
type RelocEntry (line 507) | type RelocEntry struct
type ImageImportControlTransferDynamicRelocation (line 515) | type ImageImportControlTransferDynamicRelocation struct
type ImageIndirectControlTransferDynamicRelocation (line 525) | type ImageIndirectControlTransferDynamicRelocation struct
type ImageSwitchableBranchDynamicRelocation (line 535) | type ImageSwitchableBranchDynamicRelocation struct
type DVRT (line 551) | type DVRT struct
type Enclave (line 556) | type Enclave struct
type RangeTableEntry (line 564) | type RangeTableEntry struct
type VolatileMetadata (line 569) | type VolatileMetadata struct
type LoadConfig (line 574) | type LoadConfig struct
type ImageLoadConfigCodeIntegrity (line 587) | type ImageLoadConfigCodeIntegrity struct
type ImageEnclaveConfig32 (line 597) | type ImageEnclaveConfig32 struct
type ImageEnclaveConfig64 (line 656) | type ImageEnclaveConfig64 struct
type ImageEnclaveImport (line 715) | type ImageEnclaveImport struct
type ImageVolatileMetadata (line 746) | type ImageVolatileMetadata struct
method parseLoadConfigDirectory (line 767) | func (pe *File) parseLoadConfigDirectory(rva, size uint32) error {
function StringifyGuardFlags (line 856) | func StringifyGuardFlags(flags uint32) []string {
method getSEHHandlers (line 878) | func (pe *File) getSEHHandlers() []uint32 {
method getControlFlowGuardFunctions (line 903) | func (pe *File) getControlFlowGuardFunctions() []CFGFunction {
method getControlFlowGuardIAT (line 980) | func (pe *File) getControlFlowGuardIAT() []CFGIATEntry {
method getLongJumpTargetTable (line 1047) | func (pe *File) getLongJumpTargetTable() []uint32 {
method getHybridPE (line 1095) | func (pe *File) getHybridPE() *HybridPE {
method getDynamicValueRelocTable (line 1227) | func (pe *File) getDynamicValueRelocTable() *DVRT {
method getEnclaveConfiguration (line 1395) | func (pe *File) getEnclaveConfiguration() *Enclave {
method getVolatileMetadata (line 1451) | func (pe *File) getVolatileMetadata() *VolatileMetadata {
FILE: loadconfig_test.go
function TestLoadConfigDirectory (line 12) | func TestLoadConfigDirectory(t *testing.T) {
function TestLoadConfigDirectorySEHHandlers (line 209) | func TestLoadConfigDirectorySEHHandlers(t *testing.T) {
function TestLoadConfigDirectoryControlFlowGuardFunctions (line 264) | func TestLoadConfigDirectoryControlFlowGuardFunctions(t *testing.T) {
function TestLoadConfigDirectoryControlFlowGuardIAT (line 351) | func TestLoadConfigDirectoryControlFlowGuardIAT(t *testing.T) {
function TestLoadConfigDirectoryControlFlowGuardLongJump (line 440) | func TestLoadConfigDirectoryControlFlowGuardLongJump(t *testing.T) {
function TestLoadConfigDirectoryHybridPE (line 499) | func TestLoadConfigDirectoryHybridPE(t *testing.T) {
function TestLoadConfigDirectoryDVRT (line 604) | func TestLoadConfigDirectoryDVRT(t *testing.T) {
function TestLoadConfigDirectoryDVRTRetpolineType (line 675) | func TestLoadConfigDirectoryDVRTRetpolineType(t *testing.T) {
function TestLoadConfigDirectoryEnclave (line 820) | func TestLoadConfigDirectoryEnclave(t *testing.T) {
function TestLoadConfigDirectoryVolatileMetadata (line 915) | func TestLoadConfigDirectoryVolatileMetadata(t *testing.T) {
function TestLoadConfigDirectoryCorruptSize (line 1020) | func TestLoadConfigDirectoryCorruptSize(t *testing.T) {
FILE: log/filter.go
type FilterOption (line 4) | type FilterOption
constant fuzzyStr (line 6) | fuzzyStr = "***"
function FilterLevel (line 9) | func FilterLevel(level Level) FilterOption {
function FilterKey (line 16) | func FilterKey(key ...string) FilterOption {
function FilterValue (line 25) | func FilterValue(value ...string) FilterOption {
function FilterFunc (line 34) | func FilterFunc(f func(level Level, keyvals ...interface{}) bool) Filter...
type Filter (line 41) | type Filter struct
method Log (line 63) | func (f *Filter) Log(level Level, keyvals ...interface{}) error {
function NewFilter (line 50) | func NewFilter(logger Logger, opts ...FilterOption) *Filter {
FILE: log/filter_test.go
function TestFilterAll (line 9) | func TestFilterAll(t *testing.T) {
function TestFilterLevel (line 24) | func TestFilterLevel(t *testing.T) {
function TestFilterCaller (line 34) | func TestFilterCaller(t *testing.T) {
function TestFilterKey (line 42) | func TestFilterKey(t *testing.T) {
function TestFilterValue (line 48) | func TestFilterValue(t *testing.T) {
function TestFilterFunc (line 54) | func TestFilterFunc(t *testing.T) {
function BenchmarkFilterKey (line 61) | func BenchmarkFilterKey(b *testing.B) {
function BenchmarkFilterValue (line 68) | func BenchmarkFilterValue(b *testing.B) {
function BenchmarkFilterFunc (line 75) | func BenchmarkFilterFunc(b *testing.B) {
function testFilterFunc (line 82) | func testFilterFunc(level Level, keyvals ...interface{}) bool {
function TestFilterFuncWitchLoggerPrefix (line 94) | func TestFilterFuncWitchLoggerPrefix(t *testing.T) {
function testFilterFuncWithLoggerPrefix (line 123) | func testFilterFuncWithLoggerPrefix(level Level, keyvals ...interface{})...
FILE: log/global.go
type loggerAppliance (line 12) | type loggerAppliance struct
method SetLogger (line 22) | func (a *loggerAppliance) SetLogger(in Logger) {
method GetLogger (line 29) | func (a *loggerAppliance) GetLogger() Logger {
function init (line 18) | func init() {
function SetLogger (line 35) | func SetLogger(logger Logger) {
function GetLogger (line 40) | func GetLogger() Logger {
function Log (line 45) | func Log(level Level, keyvals ...interface{}) {
function Debug (line 50) | func Debug(a ...interface{}) {
function Debugf (line 55) | func Debugf(format string, a ...interface{}) {
function Debugw (line 60) | func Debugw(keyvals ...interface{}) {
function Info (line 65) | func Info(a ...interface{}) {
function Infof (line 70) | func Infof(format string, a ...interface{}) {
function Infow (line 75) | func Infow(keyvals ...interface{}) {
function Warn (line 80) | func Warn(a ...interface{}) {
function Warnf (line 85) | func Warnf(format string, a ...interface{}) {
function Warnw (line 90) | func Warnw(keyvals ...interface{}) {
function Error (line 95) | func Error(a ...interface{}) {
function Errorf (line 100) | func Errorf(format string, a ...interface{}) {
function Errorw (line 105) | func Errorw(keyvals ...interface{}) {
function Fatal (line 110) | func Fatal(a ...interface{}) {
function Fatalf (line 115) | func Fatalf(format string, a ...interface{}) {
function Fatalw (line 120) | func Fatalw(keyvals ...interface{}) {
FILE: log/global_test.go
function TestGlobalLog (line 11) | func TestGlobalLog(t *testing.T) {
function TestGlobalLogUpdate (line 71) | func TestGlobalLogUpdate(t *testing.T) {
FILE: log/helper.go
type Option (line 13) | type Option
type Helper (line 16) | type Helper struct
method WithContext (line 42) | func (h *Helper) WithContext(ctx context.Context) *Helper {
method Log (line 50) | func (h *Helper) Log(level Level, keyvals ...interface{}) {
method Debug (line 55) | func (h *Helper) Debug(a ...interface{}) {
method Debugf (line 60) | func (h *Helper) Debugf(format string, a ...interface{}) {
method Debugw (line 65) | func (h *Helper) Debugw(keyvals ...interface{}) {
method Info (line 70) | func (h *Helper) Info(a ...interface{}) {
method Infof (line 75) | func (h *Helper) Infof(format string, a ...interface{}) {
method Infow (line 80) | func (h *Helper) Infow(keyvals ...interface{}) {
method Warn (line 85) | func (h *Helper) Warn(a ...interface{}) {
method Warnf (line 90) | func (h *Helper) Warnf(format string, a ...interface{}) {
method Warnw (line 95) | func (h *Helper) Warnw(keyvals ...interface{}) {
method Error (line 100) | func (h *Helper) Error(a ...interface{}) {
method Errorf (line 105) | func (h *Helper) Errorf(format string, a ...interface{}) {
method Errorw (line 110) | func (h *Helper) Errorw(keyvals ...interface{}) {
method Fatal (line 115) | func (h *Helper) Fatal(a ...interface{}) {
method Fatalf (line 121) | func (h *Helper) Fatalf(format string, a ...interface{}) {
method Fatalw (line 127) | func (h *Helper) Fatalw(keyvals ...interface{}) {
function WithMessageKey (line 22) | func WithMessageKey(k string) Option {
function NewHelper (line 29) | func NewHelper(logger Logger, opts ...Option) *Helper {
FILE: log/helper_test.go
function TestHelper (line 10) | func TestHelper(t *testing.T) {
function TestHelperWithMsgKey (line 24) | func TestHelperWithMsgKey(t *testing.T) {
function TestHelperLevel (line 31) | func TestHelperLevel(t *testing.T) {
function BenchmarkHelperPrint (line 42) | func BenchmarkHelperPrint(b *testing.B) {
function BenchmarkHelperPrintf (line 49) | func BenchmarkHelperPrintf(b *testing.B) {
function BenchmarkHelperPrintw (line 56) | func BenchmarkHelperPrintw(b *testing.B) {
type traceKey (line 63) | type traceKey struct
function TestContext (line 65) | func TestContext(t *testing.T) {
function Trace (line 74) | func Trace() Valuer {
FILE: log/level.go
type Level (line 6) | type Level
method String (line 24) | func (l Level) String() string {
constant LevelKey (line 9) | LevelKey = "level"
constant LevelDebug (line 13) | LevelDebug Level = iota - 1
constant LevelInfo (line 15) | LevelInfo
constant LevelWarn (line 17) | LevelWarn
constant LevelError (line 19) | LevelError
constant LevelFatal (line 21) | LevelFatal
function ParseLevel (line 42) | func ParseLevel(s string) Level {
FILE: log/level_test.go
function TestLevel_String (line 5) | func TestLevel_String(t *testing.T) {
function TestParseLevel (line 51) | func TestParseLevel(t *testing.T) {
FILE: log/log.go
type Logger (line 12) | type Logger interface
type logger (line 16) | type logger struct
method Log (line 23) | func (c *logger) Log(level Level, keyvals ...interface{}) error {
function With (line 39) | func With(l Logger, kv ...interface{}) Logger {
function WithContext (line 56) | func WithContext(ctx context.Context, l Logger) Logger {
function MultiLogger (line 69) | func MultiLogger(logs ...Logger) Logger {
FILE: log/log_test.go
function TestInfo (line 9) | func TestInfo(t *testing.T) {
function TestWrapper (line 15) | func TestWrapper(t *testing.T) {
function TestWithContext (line 23) | func TestWithContext(t *testing.T) {
FILE: log/std.go
type stdLogger (line 13) | type stdLogger struct
method Log (line 31) | func (l *stdLogger) Log(level Level, keyvals ...interface{}) error {
function NewStdLogger (line 19) | func NewStdLogger(w io.Writer) Logger {
FILE: log/std_test.go
function TestStdLogger (line 5) | func TestStdLogger(t *testing.T) {
FILE: log/value.go
type Valuer (line 21) | type Valuer
function Value (line 24) | func Value(ctx context.Context, v interface{}) interface{} {
function Caller (line 32) | func Caller(depth int) Valuer {
function Timestamp (line 50) | func Timestamp(layout string) Valuer {
function bindValues (line 56) | func bindValues(ctx context.Context, keyvals []interface{}) {
function containsValuer (line 64) | func containsValuer(keyvals []interface{}) bool {
FILE: log/value_test.go
function TestValue (line 8) | func TestValue(t *testing.T) {
FILE: ntheader.go
type ImageFileHeaderMachineType (line 12) | type ImageFileHeaderMachineType
method String (line 462) | func (t ImageFileHeaderMachineType) String() string {
type ImageFileHeaderCharacteristicsType (line 16) | type ImageFileHeaderCharacteristicsType
method String (line 498) | func (t ImageFileHeaderCharacteristicsType) String() []string {
type ImageOptionalHeaderSubsystemType (line 19) | type ImageOptionalHeaderSubsystemType
method String (line 555) | func (subsystem ImageOptionalHeaderSubsystemType) String() string {
type ImageOptionalHeaderDllCharacteristicsType (line 22) | type ImageOptionalHeaderDllCharacteristicsType
method String (line 527) | func (t ImageOptionalHeaderDllCharacteristicsType) String() []string {
type ImageNtHeader (line 26) | type ImageNtHeader struct
type ImageFileHeader (line 42) | type ImageFileHeader struct
type ImageOptionalHeader32 (line 75) | type ImageOptionalHeader32 struct
type ImageOptionalHeader64 (line 218) | type ImageOptionalHeader64 struct
type DataDirectory (line 355) | type DataDirectory struct
method ParseNTHeader (line 365) | func (pe *File) ParseNTHeader() (err error) {
method PrettyOptionalHeaderMagic (line 582) | func (pe *File) PrettyOptionalHeaderMagic() string {
FILE: ntheader_test.go
function TestParseNtHeaderNE (line 14) | func TestParseNtHeaderNE(t *testing.T) {
function TestNtHeaderMachineType (line 43) | func TestNtHeaderMachineType(t *testing.T) {
function TestNtHeaderCharacteristicsType (line 70) | func TestNtHeaderCharacteristicsType(t *testing.T) {
function TestOptionalHeaderSubsystemType (line 95) | func TestOptionalHeaderSubsystemType(t *testing.T) {
function TestOptionalHeaderDllCharacteristicsType (line 121) | func TestOptionalHeaderDllCharacteristicsType(t *testing.T) {
FILE: ordlookup.go
function OrdLookup (line 543) | func OrdLookup(libname string, ord uint64, makeName bool) string {
FILE: overlay.go
method NewOverlayReader (line 18) | func (pe *File) NewOverlayReader() (*io.SectionReader, error) {
method Overlay (line 26) | func (pe *File) Overlay() ([]byte, error) {
method OverlayLength (line 42) | func (pe *File) OverlayLength() int64 {
FILE: overlay_test.go
type TestOverlay (line 9) | type TestOverlay struct
function TestFile_NewOverlayReader (line 27) | func TestFile_NewOverlayReader(t *testing.T) {
FILE: pe.go
constant ImageDOSSignature (line 12) | ImageDOSSignature = 0x5A4D
constant ImageDOSZMSignature (line 13) | ImageDOSZMSignature = 0x4D5A
constant ImageOS2Signature (line 20) | ImageOS2Signature = 0x454E
constant ImageOS2LESignature (line 26) | ImageOS2LESignature = 0x454C
constant ImageVXDSignature (line 30) | ImageVXDSignature = 0x584C
constant ImageTESignature (line 33) | ImageTESignature = 0x5A56
constant ImageNTSignature (line 38) | ImageNTSignature = 0x00004550
constant ImageNtOptionalHeader32Magic (line 43) | ImageNtOptionalHeader32Magic = 0x10b
constant ImageNtOptionalHeader64Magic (line 44) | ImageNtOptionalHeader64Magic = 0x20b
constant ImageROMOptionalHeaderMagic (line 45) | ImageROMOptionalHeaderMagic = 0x10
constant ImageFileMachineUnknown (line 50) | ImageFileMachineUnknown = ImageFileHeaderMachineType(0x0)
constant ImageFileMachineAM33 (line 51) | ImageFileMachineAM33 = ImageFileHeaderMachineType(0x1d3)
constant ImageFileMachineAMD64 (line 52) | ImageFileMachineAMD64 = ImageFileHeaderMachineType(0x8664)
constant ImageFileMachineARM (line 53) | ImageFileMachineARM = ImageFileHeaderMachineType(0x1c0)
constant ImageFileMachineARM64 (line 54) | ImageFileMachineARM64 = ImageFileHeaderMachineType(0xaa64)
constant ImageFileMachineARMNT (line 55) | ImageFileMachineARMNT = ImageFileHeaderMachineType(0x1c4)
constant ImageFileMachineEBC (line 56) | ImageFileMachineEBC = ImageFileHeaderMachineType(0xebc)
constant ImageFileMachineI386 (line 57) | ImageFileMachineI386 = ImageFileHeaderMachineType(0x14c)
constant ImageFileMachineIA64 (line 58) | ImageFileMachineIA64 = ImageFileHeaderMachineType(0x200)
constant ImageFileMachineM32R (line 59) | ImageFileMachineM32R = ImageFileHeaderMachineType(0x9041)
constant ImageFileMachineMIPS16 (line 60) | ImageFileMachineMIPS16 = ImageFileHeaderMachineType(0x266)
constant ImageFileMachineMIPSFPU (line 61) | ImageFileMachineMIPSFPU = ImageFileHeaderMachineType(0x366)
constant ImageFileMachineMIPSFPU16 (line 62) | ImageFileMachineMIPSFPU16 = ImageFileHeaderMachineType(0x466)
constant ImageFileMachinePowerPC (line 63) | ImageFileMachinePowerPC = ImageFileHeaderMachineType(0x1f0)
constant ImageFileMachinePowerPCFP (line 64) | ImageFileMachinePowerPCFP = ImageFileHeaderMachineType(0x1f1)
constant ImageFileMachineR4000 (line 65) | ImageFileMachineR4000 = ImageFileHeaderMachineType(0x166)
constant ImageFileMachineRISCV32 (line 66) | ImageFileMachineRISCV32 = ImageFileHeaderMachineType(0x5032)
constant ImageFileMachineRISCV64 (line 67) | ImageFileMachineRISCV64 = ImageFileHeaderMachineType(0x5064)
constant ImageFileMachineRISCV128 (line 68) | ImageFileMachineRISCV128 = ImageFileHeaderMachineType(0x5128)
constant ImageFileMachineSH3 (line 69) | ImageFileMachineSH3 = ImageFileHeaderMachineType(0x1a2)
constant ImageFileMachineSH3DSP (line 70) | ImageFileMachineSH3DSP = ImageFileHeaderMachineType(0x1a3)
constant ImageFileMachineSH4 (line 71) | ImageFileMachineSH4 = ImageFileHeaderMachineType(0x1a6)
constant ImageFileMachineSH5 (line 72) | ImageFileMachineSH5 = ImageFileHeaderMachineType(0x1a8)
constant ImageFileMachineTHUMB (line 73) | ImageFileMachineTHUMB = ImageFileHeaderMachineType(0x1c2)
constant ImageFileMachineWCEMIPSv2 (line 74) | ImageFileMachineWCEMIPSv2 = ImageFileHeaderMachineType(0x169)
constant ImageFileRelocsStripped (line 83) | ImageFileRelocsStripped = 0x0001
constant ImageFileExecutableImage (line 88) | ImageFileExecutableImage = 0x0002
constant ImageFileLineNumsStripped (line 94) | ImageFileLineNumsStripped = 0x0004
constant ImageFileLocalSymsStripped (line 99) | ImageFileLocalSymsStripped = 0x0008
constant ImageFileAggressiveWSTrim (line 102) | ImageFileAggressiveWSTrim = 0x0010
constant ImageFileLargeAddressAware (line 107) | ImageFileLargeAddressAware = 0x0020
constant ImageFileBytesReservedLow (line 110) | ImageFileBytesReservedLow = 0x0080
constant ImageFile32BitMachine (line 116) | ImageFile32BitMachine = 0x0100
constant ImageFileDebugStripped (line 119) | ImageFileDebugStripped = 0x0200
constant ImageFileRemovableRunFromSwap (line 123) | ImageFileRemovableRunFromSwap = 0x0400
constant ImageFileNetRunFromSwap (line 126) | ImageFileNetRunFromSwap = 0x0800
constant ImageFileSystem (line 129) | ImageFileSystem = 0x1000
constant ImageFileDLL (line 132) | ImageFileDLL = 0x2000
constant ImageFileUpSystemOnly (line 135) | ImageFileUpSystemOnly = 0x4000
constant ImageFileBytesReservedHigh (line 138) | ImageFileBytesReservedHigh = 0x8000
constant ImageSubsystemUnknown (line 143) | ImageSubsystemUnknown = 0
constant ImageSubsystemNative (line 144) | ImageSubsystemNative = 1
constant ImageSubsystemWindowsGUI (line 145) | ImageSubsystemWindowsGUI = 2
constant ImageSubsystemWindowsCUI (line 146) | ImageSubsystemWindowsCUI = 3
constant ImageSubsystemOS2CUI (line 147) | ImageSubsystemOS2CUI = 5
constant ImageSubsystemPosixCUI (line 148) | ImageSubsystemPosixCUI = 7
constant ImageSubsystemNativeWindows (line 149) | ImageSubsystemNativeWindows = 8
constant ImageSubsystemWindowsCEGUI (line 150) | ImageSubsystemWindowsCEGUI = 9
constant ImageSubsystemEFIApplication (line 151) | ImageSubsystemEFIApplication = 10
constant ImageSubsystemEFIBootServiceDriver (line 152) | ImageSubsystemEFIBootServiceDriver = 11
constant ImageSubsystemEFIRuntimeDriver (line 153) | ImageSubsystemEFIRuntimeDriver = 12
constant ImageSubsystemEFIRom (line 154) | ImageSubsystemEFIRom = 13
constant ImageSubsystemXBOX (line 155) | ImageSubsystemXBOX = 14
constant ImageSubsystemWindowsBootApplication (line 156) | ImageSubsystemWindowsBootApplication = 16
constant ImageDllCharacteristicsReserved1 (line 161) | ImageDllCharacteristicsReserved1 = 0x0001
constant ImageDllCharacteristicsReserved2 (line 162) | ImageDllCharacteristicsReserved2 = 0x0002
constant ImageDllCharacteristicsReserved4 (line 163) | ImageDllCharacteristicsReserved4 = 0x0004
constant ImageDllCharacteristicsReserved8 (line 164) | ImageDllCharacteristicsReserved8 = 0x0008
constant ImageDllCharacteristicsHighEntropyVA (line 165) | ImageDllCharacteristicsHighEntropyVA = 0x0020
constant ImageDllCharacteristicsDynamicBase (line 166) | ImageDllCharacteristicsDynamicBase = 0x0040
constant ImageDllCharacteristicsForceIntegrity (line 167) | ImageDllCharacteristicsForceIntegrity = 0x0080
constant ImageDllCharacteristicsNXCompact (line 168) | ImageDllCharacteristicsNXCompact = 0x0100
constant ImageDllCharacteristicsNoIsolation (line 169) | ImageDllCharacteristicsNoIsolation = 0x0200
constant ImageDllCharacteristicsNoSEH (line 170) | ImageDllCharacteristicsNoSEH = 0x0400
constant ImageDllCharacteristicsNoBind (line 171) | ImageDllCharacteristicsNoBind = 0x0800
constant ImageDllCharacteristicsAppContainer (line 172) | ImageDllCharacteristicsAppContainer = 0x1000
constant ImageDllCharacteristicsWdmDriver (line 173) | ImageDllCharacteristicsWdmDriver = 0x2000
constant ImageDllCharacteristicsGuardCF (line 174) | ImageDllCharacteristicsGuardCF = 0x4000
constant ImageDllCharacteristicsTerminalServiceAware (line 175) | ImageDllCharacteristicsTerminalServiceAware = 0x8000
type ImageDirectoryEntry (line 180) | type ImageDirectoryEntry
constant ImageDirectoryEntryExport (line 184) | ImageDirectoryEntryExport ImageDirectoryEntry = iota
constant ImageDirectoryEntryImport (line 185) | ImageDirectoryEntryImport
constant ImageDirectoryEntryResource (line 186) | ImageDirectoryEntryResource
constant ImageDirectoryEntryException (line 187) | ImageDirectoryEntryException
constant ImageDirectoryEntryCertificate (line 188) | ImageDirectoryEntryCertificate
constant ImageDirectoryEntryBaseReloc (line 189) | ImageDirectoryEntryBaseReloc
constant ImageDirectoryEntryDebug (line 190) | ImageDirectoryEntryDebug
constant ImageDirectoryEntryArchitecture (line 191) | ImageDirectoryEntryArchitecture
constant ImageDirectoryEntryGlobalPtr (line 192) | ImageDirectoryEntryGlobalPtr
constant ImageDirectoryEntryTLS (line 193) | ImageDirectoryEntryTLS
constant ImageDirectoryEntryLoadConfig (line 194) | ImageDirectoryEntryLoadConfig
constant ImageDirectoryEntryBoundImport (line 195) | ImageDirectoryEntryBoundImport
constant ImageDirectoryEntryIAT (line 196) | ImageDirectoryEntryIAT
constant ImageDirectoryEntryDelayImport (line 197) | ImageDirectoryEntryDelayImport
constant ImageDirectoryEntryCLR (line 198) | ImageDirectoryEntryCLR
constant ImageDirectoryEntryReserved (line 199) | ImageDirectoryEntryReserved
constant ImageNumberOfDirectoryEntries (line 200) | ImageNumberOfDirectoryEntries
type FileInfo (line 204) | type FileInfo struct
FILE: reloc.go
type ImageBaseRelocationEntryType (line 23) | type ImageBaseRelocationEntryType
method String (line 248) | func (t ImageBaseRelocationEntryType) String(pe *File) string {
constant ImageRelBasedAbsolute (line 30) | ImageRelBasedAbsolute = 0
constant ImageRelBasedHigh (line 34) | ImageRelBasedHigh = 1
constant ImageRelBasedLow (line 38) | ImageRelBasedLow = 2
constant ImageRelBasedHighLow (line 42) | ImageRelBasedHighLow = 3
constant ImageRelBasedHighAdj (line 49) | ImageRelBasedHighAdj = 4
constant ImageRelBasedMIPSJmpAddr (line 54) | ImageRelBasedMIPSJmpAddr = 5
constant ImageRelBasedARMMov32 (line 59) | ImageRelBasedARMMov32 = 5
constant ImageRelBasedRISCVHigh20 (line 63) | ImageRelBasedRISCVHigh20 = 5
constant ImageRelReserved (line 66) | ImageRelReserved = 6
constant ImageRelBasedThumbMov32 (line 71) | ImageRelBasedThumbMov32 = 7
constant ImageRelBasedRISCVLow12i (line 76) | ImageRelBasedRISCVLow12i = 7
constant ImageRelBasedRISCVLow12s (line 81) | ImageRelBasedRISCVLow12s = 8
constant ImageRelBasedMIPSJmpAddr16 (line 85) | ImageRelBasedMIPSJmpAddr16 = 9
constant ImageRelBasedDir64 (line 88) | ImageRelBasedDir64 = 10
constant MaxDefaultRelocEntriesCount (line 96) | MaxDefaultRelocEntriesCount = 0x1000
type ImageBaseRelocation (line 101) | type ImageBaseRelocation struct
type ImageBaseRelocationEntry (line 112) | type ImageBaseRelocationEntry struct
type Relocation (line 128) | type Relocation struct
method parseRelocations (line 136) | func (pe *File) parseRelocations(dataRVA, rva, size uint32) ([]ImageBase...
method parseRelocDirectory (line 165) | func (pe *File) parseRelocDirectory(rva, size uint32) error {
FILE: reloc_test.go
function TestParseRelocDirectoryData (line 11) | func TestParseRelocDirectoryData(t *testing.T) {
function TestParseRelocDirectoryZeroSizeOfBlock (line 90) | func TestParseRelocDirectoryZeroSizeOfBlock(t *testing.T) {
function TestParseRelocDirectoryEntry (line 152) | func TestParseRelocDirectoryEntry(t *testing.T) {
FILE: resource.go
type ResourceType (line 12) | type ResourceType
method String (line 1195) | func (rt ResourceType) String() string {
type ResourceLang (line 15) | type ResourceLang
method String (line 1229) | func (lang ResourceLang) String() string {
type ResourceSubLang (line 18) | type ResourceSubLang
method String (line 1381) | func (subLang ResourceSubLang) String() string {
constant LangNeutral (line 24) | LangNeutral ResourceLang = 0x00
constant LangUserDefault (line 25) | LangUserDefault ResourceLang = 0x01
constant LangSystemDefault (line 26) | LangSystemDefault ResourceLang = 0x02
constant LangInvariant (line 27) | LangInvariant ResourceLang = 0x7F
constant SubLangNeutral (line 29) | SubLangNeutral ResourceSubLang = 0x00
constant SubLangInvariant (line 30) | SubLangInvariant ResourceSubLang = 0x00
constant SubLangDefault (line 31) | SubLangDefault ResourceSubLang = 0x01
constant SubLangSysDefault (line 32) | SubLangSysDefault ResourceSubLang = 0x02
constant SubLangCustomDefault (line 33) | SubLangCustomDefault ResourceSubLang = 0x03
constant SubLangCustomUnspecified (line 34) | SubLangCustomUnspecified ResourceSubLang = 0x04
constant SubLangMUICustomDefault (line 35) | SubLangMUICustomDefault ResourceSubLang = 0x05
constant LangAfrikaans (line 41) | LangAfrikaans ResourceLang = 0x0036
constant LangAlbanian (line 43) | LangAlbanian ResourceLang = 0x001C
constant LangAlsatian (line 45) | LangAlsatian ResourceLang = 0x0084
constant LangAmharic (line 47) | LangAmharic ResourceLang = 0x005E
constant LangArabic (line 49) | LangArabic ResourceLang = 0x0001
constant LangArmenian (line 51) | LangArmenian ResourceLang = 0x002B
constant LangAssamese (line 53) | LangAssamese ResourceLang = 0x004D
constant LangAzerbaijaniLatin (line 55) | LangAzerbaijaniLatin ResourceLang = 0x002C
constant LangBangla (line 57) | LangBangla ResourceLang = 0x0045
constant LangBashkir (line 59) | LangBashkir ResourceLang = 0x006D
constant LangBasque (line 61) | LangBasque ResourceLang = 0x002D
constant LangBelarusian (line 63) | LangBelarusian ResourceLang = 0x0023
constant LangBosnianLatin (line 65) | LangBosnianLatin ResourceLang = 0x781A
constant LangBreton (line 67) | LangBreton ResourceLang = 0x007E
constant LangBulgarian (line 69) | LangBulgarian ResourceLang = 0x0002
constant LangBurmese (line 71) | LangBurmese ResourceLang = 0x0055
constant LangCatalan (line 73) | LangCatalan ResourceLang = 0x0003
constant LangCentralKurdish (line 75) | LangCentralKurdish ResourceLang = 0x0092
constant LangCherokee (line 77) | LangCherokee ResourceLang = 0x005C
constant LangChineseSimplified (line 79) | LangChineseSimplified ResourceLang = 0x7804
constant LangCorsican (line 81) | LangCorsican ResourceLang = 0x0083
constant LangCroatian (line 83) | LangCroatian ResourceLang = 0x001A
constant LangCzech (line 85) | LangCzech ResourceLang = 0x0005
constant LangDanish (line 87) | LangDanish ResourceLang = 0x0006
constant LangDari (line 89) | LangDari ResourceLang = 0x008C
constant LangDivehi (line 91) | LangDivehi ResourceLang = 0x0065
constant LangDutch (line 93) | LangDutch ResourceLang = 0x0013
constant LangEnglish (line 95) | LangEnglish ResourceLang = 0x0009
constant LangEstonian (line 97) | LangEstonian ResourceLang = 0x0025
constant LangFaroese (line 99) | LangFaroese ResourceLang = 0x0038
constant LangFilipino (line 101) | LangFilipino ResourceLang = 0x0064
constant LangFinnish (line 103) | LangFinnish ResourceLang = 0x000B
constant LangFrench (line 105) | LangFrench ResourceLang = 0x000C
constant LangFrisian (line 107) | LangFrisian ResourceLang = 0x0062
constant LangFulah (line 109) | LangFulah ResourceLang = 0x0067
constant LangFulahLatin (line 111) | LangFulahLatin ResourceLang = 0x7C67
constant LangGalician (line 113) | LangGalician ResourceLang = 0x0056
constant LangGeorgian (line 115) | LangGeorgian ResourceLang = 0x0037
constant LangGerman (line 117) | LangGerman ResourceLang = 0x0007
constant LangGreek (line 119) | LangGreek ResourceLang = 0x0008
constant LangGreenlandic (line 121) | LangGreenlandic ResourceLang = 0x006F
constant LangGuarani (line 123) | LangGuarani ResourceLang = 0x0074
constant LangGujarati (line 125) | LangGujarati ResourceLang = 0x0047
constant LangHausaLatin (line 127) | LangHausaLatin ResourceLang = 0x0068
constant LangHawaiian (line 129) | LangHawaiian ResourceLang = 0x0075
constant LangHebrew (line 131) | LangHebrew ResourceLang = 0x000D
constant LangHindi (line 133) | LangHindi ResourceLang = 0x0039
constant LangHungarian (line 135) | LangHungarian ResourceLang = 0x000E
constant LangIcelandic (line 137) | LangIcelandic ResourceLang = 0x000F
constant LangIgbo (line 139) | LangIgbo ResourceLang = 0x0070
constant LangIndonesian (line 141) | LangIndonesian ResourceLang = 0x0021
constant LangInuktitutLatin (line 143) | LangInuktitutLatin ResourceLang = 0x005D
constant LangIrish (line 145) | LangIrish ResourceLang = 0x003C
constant LangItalian (line 147) | LangItalian ResourceLang = 0x0010
constant LangJapanese (line 149) | LangJapanese ResourceLang = 0x0011
constant LangKannada (line 151) | LangKannada ResourceLang = 0x004B
constant LangKashmiri (line 153) | LangKashmiri ResourceLang = 0x0060
constant LangKazakh (line 155) | LangKazakh ResourceLang = 0x003F
constant LangKhmer (line 157) | LangKhmer ResourceLang = 0x0053
constant LangKiche (line 159) | LangKiche ResourceLang = 0x0086
constant LangKinyarwanda (line 161) | LangKinyarwanda ResourceLang = 0x0087
constant LangKiswahili (line 163) | LangKiswahili ResourceLang = 0x0041
constant LangKonkani (line 165) | LangKonkani ResourceLang = 0x0057
constant LangKorean (line 167) | LangKorean ResourceLang = 0x0012
constant LangKyrgyz (line 169) | LangKyrgyz ResourceLang = 0x0040
constant LangLao (line 171) | LangLao ResourceLang = 0x0054
constant LangLatvian (line 173) | LangLatvian ResourceLang = 0x0026
constant LangLithuanian (line 175) | LangLithuanian ResourceLang = 0x0027
constant LangLowerSorbian (line 177) | LangLowerSorbian ResourceLang = 0x7C2E
constant LangLuxembourgish (line 179) | LangLuxembourgish ResourceLang = 0x006E
constant LangMacedonian (line 181) | LangMacedonian ResourceLang = 0x002F
constant LangMalay (line 183) | LangMalay ResourceLang = 0x003E
constant LangMalayalam (line 185) | LangMalayalam ResourceLang = 0x004C
constant LangMaltese (line 187) | LangMaltese ResourceLang = 0x003A
constant LangMaori (line 189) | LangMaori ResourceLang = 0x0081
constant LangMapudungun (line 191) | LangMapudungun ResourceLang = 0x007A
constant LangMarathi (line 193) | LangMarathi ResourceLang = 0x004E
constant LangMohawk (line 195) | LangMohawk ResourceLang = 0x007C
constant LangMongolianCyrillic (line 197) | LangMongolianCyrillic ResourceLang = 0x0050
constant LangNepali (line 199) | LangNepali ResourceLang = 0x0061
constant LangNorwegianBokmalNo (line 201) | LangNorwegianBokmalNo ResourceLang = 0x0014
constant LangNorwegianBokmal (line 203) | LangNorwegianBokmal ResourceLang = 0x7C14
constant LangNorwegianNynorsk (line 205) | LangNorwegianNynorsk ResourceLang = 0x7814
constant LangOccitan (line 207) | LangOccitan ResourceLang = 0x0082
constant LangOdia (line 209) | LangOdia ResourceLang = 0x0048
constant LangOromo (line 211) | LangOromo ResourceLang = 0x0072
constant LangPashto (line 213) | LangPashto ResourceLang = 0x0063
constant LangPersian (line 215) | LangPersian ResourceLang = 0x0029
constant LangPolish (line 217) | LangPolish ResourceLang = 0x0015
constant LangPortuguese (line 219) | LangPortuguese ResourceLang = 0x0016
constant LangPunjabi (line 221) | LangPunjabi ResourceLang = 0x0046
constant LangQuechua (line 223) | LangQuechua ResourceLang = 0x006B
constant LangRomanian (line 225) | LangRomanian ResourceLang = 0x0018
constant LangRomansh (line 227) | LangRomansh ResourceLang = 0x0017
constant LangRussian (line 229) | LangRussian ResourceLang = 0x0019
constant LangSakha (line 231) | LangSakha ResourceLang = 0x0085
constant LangSamiInari (line 233) | LangSamiInari ResourceLang = 0x703B
constant LangSamiLule (line 235) | LangSamiLule ResourceLang = 0x7C3B
constant LangSamiNorthern (line 237) | LangSamiNorthern ResourceLang = 0x003B
constant LangSamiSkolt (line 239) | LangSamiSkolt ResourceLang = 0x743B
constant LangSamiSouthern (line 241) | LangSamiSouthern ResourceLang = 0x783B
constant LangSanskrit (line 243) | LangSanskrit ResourceLang = 0x004F
constant LangScottishGaelic (line 245) | LangScottishGaelic ResourceLang = 0x0091
constant LangSerbianLatin (line 247) | LangSerbianLatin ResourceLang = 0x7C1A
constant LangSesothoSaLeboa (line 249) | LangSesothoSaLeboa ResourceLang = 0x006C
constant LangSetswana (line 251) | LangSetswana ResourceLang = 0x0032
constant LangSindhi (line 253) | LangSindhi ResourceLang = 0x0059
constant LangSinhala (line 255) | LangSinhala ResourceLang = 0x005B
constant LangSlovak (line 257) | LangSlovak ResourceLang = 0x001B
constant LangSlovenian (line 259) | LangSlovenian ResourceLang = 0x0024
constant LangSomali (line 261) | LangSomali ResourceLang = 0x0077
constant LangSotho (line 263) | LangSotho ResourceLang = 0x0030
constant LangSpanish (line 265) | LangSpanish ResourceLang = 0x000A
constant LangSwedish (line 267) | LangSwedish ResourceLang = 0x001D
constant LangSyriac (line 269) | LangSyriac ResourceLang = 0x005A
constant LangTajikCyrillic (line 271) | LangTajikCyrillic ResourceLang = 0x0028
constant LangTamazightLatin (line 273) | LangTamazightLatin ResourceLang = 0x005F
constant LangTamil (line 275) | LangTamil ResourceLang = 0x0049
constant LangTatar (line 277) | LangTatar ResourceLang = 0x0044
constant LangTelugu (line 279) | LangTelugu ResourceLang = 0x004A
constant LangThai (line 281) | LangThai ResourceLang = 0x001E
constant LangTibetan (line 283) | LangTibetan ResourceLang = 0x0051
constant LangTigrinya (line 285) | LangTigrinya ResourceLang = 0x0073
constant LangTsonga (line 287) | LangTsonga ResourceLang = 0x0031
constant LangTurkish (line 289) | LangTurkish ResourceLang = 0x001F
constant LangTurkmen (line 291) | LangTurkmen ResourceLang = 0x0042
constant LangUkrainian (line 293) | LangUkrainian ResourceLang = 0x0022
constant LangUpperSorbian (line 295) | LangUpperSorbian ResourceLang = 0x002E
constant LangUrdu (line 297) | LangUrdu ResourceLang = 0x0020
constant LangUyghur (line 299) | LangUyghur ResourceLang = 0x0080
constant LangUzbekLatin (line 301) | LangUzbekLatin ResourceLang = 0x0043
constant LangVenda (line 303) | LangVenda ResourceLang = 0x0033
constant LangVietnamese (line 305) | LangVietnamese ResourceLang = 0x002A
constant LangWelsh (line 307) | LangWelsh ResourceLang = 0x0052
constant LangWolof (line 309) | LangWolof ResourceLang = 0x0088
constant LangXhosa (line 311) | LangXhosa ResourceLang = 0x0034
constant LangYi (line 313) | LangYi ResourceLang = 0x0078
constant LangYoruba (line 315) | LangYoruba ResourceLang = 0x006A
constant LangZulu (line 317) | LangZulu ResourceLang = 0x0035
constant SubLangAfrikaansSouthAfrica (line 323) | SubLangAfrikaansSouthAfrica ResourceSubLang = iota
constant SubLangAlbanianAlbania (line 325) | SubLangAlbanianAlbania
constant SubLangAlsatianFrance (line 327) | SubLangAlsatianFrance
constant SubLangAmharicEthiopia (line 329) | SubLangAmharicEthiopia
constant SubLangArabicAlgeria (line 331) | SubLangArabicAlgeria
constant SubLangArabicBahrain (line 333) | SubLangArabicBahrain
constant SubLangArabicEgypt (line 335) | SubLangArabicEgypt
constant SubLangArabicIraq (line 337) | SubLangArabicIraq
constant SubLangArabicJordan (line 339) | SubLangArabicJordan
constant SubLangArabicKuwait (line 341) | SubLangArabicKuwait
constant SubLangArabicLebanon (line 343) | SubLangArabicLebanon
constant SubLangArabicLibya (line 345) | SubLangArabicLibya
constant SubLangArabicMorocco (line 347) | SubLangArabicMorocco
constant SubLangArabicOman (line 349) | SubLangArabicOman
constant SubLangArabicQatar (line 351) | SubLangArabicQatar
constant SubLangArabicSaudiArabia (line 353) | SubLangArabicSaudiArabia
constant SubLangArabicSyria (line 355) | SubLangArabicSyria
constant SubLangArabicTunisia (line 357) | SubLangArabicTunisia
constant SubLangArabicUae (line 359) | SubLangArabicUae
constant SubLangArabicYemen (line 361) | SubLangArabicYemen
constant SubLangArmenianArmenia (line 363) | SubLangArmenianArmenia
constant SubLangAssameseIndia (line 365) | SubLangAssameseIndia
constant SubLangAzerbaijaniCyrillic (line 367) | SubLangAzerbaijaniCyrillic
constant SubLangAzerbaijaniCyrillicAzerbaijan (line 369) | SubLangAzerbaijaniCyrillicAzerbaijan
constant SubLangAzerbaijaniLatin (line 371) | SubLangAzerbaijaniLatin
constant SubLangAzerbaijaniLatinAzerbaijan (line 373) | SubLangAzerbaijaniLatinAzerbaijan
constant SubLangBanglaBangladesh (line 375) | SubLangBanglaBangladesh
constant SubLangBanglaIndia (line 377) | SubLangBanglaIndia
constant SubLangBashkirRussia (line 379) | SubLangBashkirRussia
constant SubLangBasqueSpain (line 381) | SubLangBasqueSpain
constant SubLangBelarusianBelarus (line 383) | SubLangBelarusianBelarus
constant SubLangBosnianCyrillic (line 385) | SubLangBosnianCyrillic
constant SubLangBosnianCyrillicBosniaAndHerzegovina (line 387) | SubLangBosnianCyrillicBosniaAndHerzegovina
constant SubLangBosnianLatin (line 389) | SubLangBosnianLatin
constant SubLangBosnianLatinBosniaAndHerzegovina (line 391) | SubLangBosnianLatinBosniaAndHerzegovina
constant SubLangBretonFrance (line 393) | SubLangBretonFrance
constant SubLangBulgarianBulgaria (line 395) | SubLangBulgarianBulgaria
constant SubLangBurmeseMyanmar (line 397) | SubLangBurmeseMyanmar
constant SubLangCatalanSpain (line 399) | SubLangCatalanSpain
constant SubLangCentralAtlasTamazightArabicMorocco (line 401) | SubLangCentralAtlasTamazightArabicMorocco
constant SubLangCentralKurdish (line 403) | SubLangCentralKurdish
constant SubLangCentralKurdishIraq (line 405) | SubLangCentralKurdishIraq
constant SubLangCherokee (line 407) | SubLangCherokee
constant SubLangCherokeeUnitedStates (line 409) | SubLangCherokeeUnitedStates
constant SubLangChineseSimplified (line 411) | SubLangChineseSimplified
constant SubLangChineseSimplifiedPeoplesRepublicOfChina (line 413) | SubLangChineseSimplifiedPeoplesRepublicOfChina
constant SubLangChineseSimplifiedSingapore (line 415) | SubLangChineseSimplifiedSingapore
constant SubLangChineseTraditional (line 417) | SubLangChineseTraditional
constant SubLangChineseTraditionalHongKongSar (line 419) | SubLangChineseTraditionalHongKongSar
constant SubLangChineseTraditionalMacaoSar (line 421) | SubLangChineseTraditionalMacaoSar
constant SubLangChineseTraditionalTaiwan (line 423) | SubLangChineseTraditionalTaiwan
constant SubLangCorsicanFrance (line 425) | SubLangCorsicanFrance
constant SubLangCroatianCroatia (line 427) | SubLangCroatianCroatia
constant SubLangCroatianLatinBosniaAndHerzegovina (line 429) | SubLangCroatianLatinBosniaAndHerzegovina
constant SubLangCzechCzechRepublic (line 431) | SubLangCzechCzechRepublic
constant SubLangDanishDenmark (line 433) | SubLangDanishDenmark
constant SubLangDariAfghanistan (line 435) | SubLangDariAfghanistan
constant SubLangDivehiMaldives (line 437) | SubLangDivehiMaldives
constant SubLangDutchBelgium (line 439) | SubLangDutchBelgium
constant SubLangDutchNetherlands (line 441) | SubLangDutchNetherlands
constant SubLangDzongkhaBhutan (line 443) | SubLangDzongkhaBhutan
constant SubLangEnglishAustralia (line 445) | SubLangEnglishAustralia
constant SubLangEnglishBelize (line 447) | SubLangEnglishBelize
constant SubLangEnglishCanada (line 449) | SubLangEnglishCanada
constant SubLangEnglishCaribbean (line 451) | SubLangEnglishCaribbean
constant SubLangEnglishHongKong (line 453) | SubLangEnglishHongKong
constant SubLangEnglishIndia (line 455) | SubLangEnglishIndia
constant SubLangEnglishIreland (line 457) | SubLangEnglishIreland
constant SubLangEnglishJamaica (line 459) | SubLangEnglishJamaica
constant SubLangEnglishMalaysia (line 461) | SubLangEnglishMalaysia
constant SubLangEnglishNewZealand (line 463) | SubLangEnglishNewZealand
constant SubLangEnglishRepublicOfThePhilippines (line 465) | SubLangEnglishRepublicOfThePhilippines
constant SubLangEnglishSingapore (line 467) | SubLangEnglishSingapore
constant SubLangEnglishSouthAfrica (line 469) | SubLangEnglishSouthAfrica
constant SubLangEnglishTrinidadAndTobago (line 471) | SubLangEnglishTrinidadAndTobago
constant SubLangEnglishUnitedArabEmirates (line 473) | SubLangEnglishUnitedArabEmirates
constant SubLangEnglishUnitedKingdom (line 475) | SubLangEnglishUnitedKingdom
constant SubLangEnglishUnitedStates (line 477) | SubLangEnglishUnitedStates
constant SubLangEnglishZimbabwe (line 479) | SubLangEnglishZimbabwe
constant SubLangEstonianEstonia (line 481) | SubLangEstonianEstonia
constant SubLangFaroeseFaroeIslands (line 483) | SubLangFaroeseFaroeIslands
constant SubLangFilipinoPhilippines (line 485) | SubLangFilipinoPhilippines
constant SubLangFinnishFinland (line 487) | SubLangFinnishFinland
constant SubLangFrenchBelgium (line 489) | SubLangFrenchBelgium
constant SubLangFrenchCameroon (line 491) | SubLangFrenchCameroon
constant SubLangFrenchCanada (line 493) | SubLangFrenchCanada
constant SubLangFrenchCaribbean (line 495) | SubLangFrenchCaribbean
constant SubLangFrenchCongoDrc (line 497) | SubLangFrenchCongoDrc
constant SubLangFrenchCôteDivoire (line 499) | SubLangFrenchCôteDivoire
constant SubLangFrenchFrance (line 501) | SubLangFrenchFrance
constant SubLangFrenchHaiti (line 503) | SubLangFrenchHaiti
constant SubLangFrenchLuxembourg (line 505) | SubLangFrenchLuxembourg
constant SubLangFrenchMali (line 507) | SubLangFrenchMali
constant SubLangFrenchMorocco (line 509) | SubLangFrenchMorocco
constant SubLangFrenchPrincipalityOfMonaco (line 511) | SubLangFrenchPrincipalityOfMonaco
constant SubLangFrenchReunion (line 513) | SubLangFrenchReunion
constant SubLangFrenchSenegal (line 515) | SubLangFrenchSenegal
constant SubLangFrenchSwitzerland (line 517) | SubLangFrenchSwitzerland
constant SubLangFrisianNetherlands (line 519) | SubLangFrisianNetherlands
constant SubLangFulahNigeria (line 521) | SubLangFulahNigeria
constant SubLangFulahLatinNigeria (line 523) | SubLangFulahLatinNigeria
constant SubLangFulahSenegal (line 525) | SubLangFulahSenegal
constant SubLangGalicianSpain (line 527) | SubLangGalicianSpain
constant SubLangGeorgianGeorgia (line 529) | SubLangGeorgianGeorgia
constant SubLangGermanAustria (line 531) | SubLangGermanAustria
constant SubLangGermanGermany (line 533) | SubLangGermanGermany
constant SubLangGermanLiechtenstein (line 535) | SubLangGermanLiechtenstein
constant SubLangGermanLuxembourg (line 537) | SubLangGermanLuxembourg
constant SubLangGermanSwitzerland (line 539) | SubLangGermanSwitzerland
constant SubLangGreekGreece (line 541) | SubLangGreekGreece
constant SubLangGreenlandicGreenland (line 543) | SubLangGreenlandicGreenland
constant SubLangGuaraniParaguay (line 545) | SubLangGuaraniParaguay
constant SubLangGujaratiIndia (line 547) | SubLangGujaratiIndia
constant SubLangHausaLatin (line 549) | SubLangHausaLatin
constant SubLangHausaLatinNigeria (line 551) | SubLangHausaLatinNigeria
constant SubLangHawaiianUnitedStates (line 553) | SubLangHawaiianUnitedStates
constant SubLangHebrewIsrael (line 555) | SubLangHebrewIsrael
constant SubLangHindiIndia (line 557) | SubLangHindiIndia
constant SubLangHungarianHungary (line 559) | SubLangHungarianHungary
constant SubLangIcelandicIceland (line 561) | SubLangIcelandicIceland
constant SubLangIgboNigeria (line 563) | SubLangIgboNigeria
constant SubLangIndonesianIndonesia (line 565) | SubLangIndonesianIndonesia
constant SubLangInuktitutLatin (line 567) | SubLangInuktitutLatin
constant SubLangInuktitutLatinCanada (line 569) | SubLangInuktitutLatinCanada
constant SubLangInuktitutSyllabics (line 571) | SubLangInuktitutSyllabics
constant SubLangInuktitutSyllabicsCanada (line 573) | SubLangInuktitutSyllabicsCanada
constant SubLangIrishIreland (line 575) | SubLangIrishIreland
constant SubLangItalianItaly (line 577) | SubLangItalianItaly
constant SubLangItalianSwitzerland (line 579) | SubLangItalianSwitzerland
constant SubLangJapaneseJapan (line 581) | SubLangJapaneseJapan
constant SubLangKannadaIndia (line 583) | SubLangKannadaIndia
constant SubLangKanuriLatinNigeria (line 585) | SubLangKanuriLatinNigeria
constant SubLangKashmiriPersoArabic (line 587) | SubLangKashmiriPersoArabic
constant SubLangKashmiriDevanagariIndia (line 589) | SubLangKashmiriDevanagariIndia
constant SubLangKazakhKazakhstan (line 591) | SubLangKazakhKazakhstan
constant SubLangKhmerCambodia (line 593) | SubLangKhmerCambodia
constant SubLangKicheGuatemala (line 595) | SubLangKicheGuatemala
constant SubLangKinyarwandaRwanda (line 597) | SubLangKinyarwandaRwanda
constant SubLangKiswahiliKenya (line 599) | SubLangKiswahiliKenya
constant SubLangKonkaniIndia (line 601) | SubLangKonkaniIndia
constant SubLangKoreanKorea (line 603) | SubLangKoreanKorea
constant SubLangKyrgyzKyrgyzstan (line 605) | SubLangKyrgyzKyrgyzstan
constant SubLangLaoLaoPdr (line 607) | SubLangLaoLaoPdr
constant SubLangLatinVaticanCity (line 609) | SubLangLatinVaticanCity
constant SubLangLatvianLatvia (line 611) | SubLangLatvianLatvia
constant SubLangLithuanianLithuania (line 613) | SubLangLithuanianLithuania
constant SubLangLowerSorbianGermany (line 615) | SubLangLowerSorbianGermany
constant SubLangLuxembourgishLuxembourg (line 617) | SubLangLuxembourgishLuxembourg
constant SubLangMacedonianNorthMacedonia (line 619) | SubLangMacedonianNorthMacedonia
constant SubLangMalayBruneiDarussalam (line 621) | SubLangMalayBruneiDarussalam
constant SubLangMalayMalaysia (line 623) | SubLangMalayMalaysia
constant SubLangMalayalamIndia (line 625) | SubLangMalayalamIndia
constant SubLangMalteseMalta (line 627) | SubLangMalteseMalta
constant SubLangMaoriNewZealand (line 629) | SubLangMaoriNewZealand
constant SubLangMapudungunChile (line 631) | SubLangMapudungunChile
constant SubLangMarathiIndia (line 633) | SubLangMarathiIndia
constant SubLangMohawkCanada (line 635) | SubLangMohawkCanada
constant SubLangMongolianCyrillic (line 637) | SubLangMongolianCyrillic
constant SubLangMongolianCyrillicMongolia (line 639) | SubLangMongolianCyrillicMongolia
constant SubLangMongolianTraditionalMongolian (line 641) | SubLangMongolianTraditionalMongolian
constant SubLangMongolianTraditionalMongolianPeoplesRepublicOfChina (line 643) | SubLangMongolianTraditionalMongolianPeoplesRepublicOfChina
constant SubLangMongolianTraditionalMongolianMongolia (line 645) | SubLangMongolianTraditionalMongolianMongolia
constant SubLangNepaliIndia (line 647) | SubLangNepaliIndia
constant SubLangNepaliNepal (line 649) | SubLangNepaliNepal
constant SubLangNorwegianBokmalNorway (line 651) | SubLangNorwegianBokmalNorway
constant SubLangNorwegianNynorskNorway (line 653) | SubLangNorwegianNynorskNorway
constant SubLangOccitanFrance (line 655) | SubLangOccitanFrance
constant SubLangOdiaIndia (line 657) | SubLangOdiaIndia
constant SubLangOromoEthiopia (line 659) | SubLangOromoEthiopia
constant SubLangPashtoAfghanistan (line 661) | SubLangPashtoAfghanistan
constant SubLangPersianIran (line 663) | SubLangPersianIran
constant SubLangPolishPoland (line 665) | SubLangPolishPoland
constant SubLangPortugueseBrazil (line 667) | SubLangPortugueseBrazil
constant SubLangPortuguesePortugal (line 669) | SubLangPortuguesePortugal
constant SubLangPseudoLanguagePseudoLocaleForEastAsianComplexScriptLocalizationTesting (line 671) | SubLangPseudoLanguagePseudoLocaleForEastAsianComplexScriptLocalizationTe...
constant SubLangPseudoLanguagePseudoLocaleUsedForLocalizationTesting (line 673) | SubLangPseudoLanguagePseudoLocaleUsedForLocalizationTesting
constant SubLangPseudoLanguagePseudoLocaleUsedForLocalizationTestingOfMirroredLocales (line 675) | SubLangPseudoLanguagePseudoLocaleUsedForLocalizationTestingOfMirroredLoc...
constant SubLangPunjabi (line 677) | SubLangPunjabi
constant SubLangPunjabiIndia (line 679) | SubLangPunjabiIndia
constant SubLangPunjabiIslamicRepublicOfPakistan (line 681) | SubLangPunjabiIslamicRepublicOfPakistan
constant SubLangQuechuaBolivia (line 683) | SubLangQuechuaBolivia
constant SubLangQuechuaEcuador (line 685) | SubLangQuechuaEcuador
constant SubLangQuechuaPeru (line 687) | SubLangQuechuaPeru
constant SubLangRomanianMoldova (line 689) | SubLangRomanianMoldova
constant SubLangRomanianRomania (line 691) | SubLangRomanianRomania
constant SubLangRomanshSwitzerland (line 693) | SubLangRomanshSwitzerland
constant SubLangRussianMoldova (line 695) | SubLangRussianMoldova
constant SubLangRussianRussia (line 697) | SubLangRussianRussia
constant SubLangSakhaRussia (line 699) | SubLangSakhaRussia
constant SubLangSamiInariFinland (line 701) | SubLangSamiInariFinland
constant SubLangSamiLuleNorway (line 703) | SubLangSamiLuleNorway
constant SubLangSamiLuleSweden (line 705) | SubLangSamiLuleSweden
constant SubLangSamiNorthernFinland (line 707) | SubLangSamiNorthernFinland
constant SubLangSamiNorthernNorway (line 709) | SubLangSamiNorthernNorway
constant SubLangSamiNorthernSweden (line 711) | SubLangSamiNorthernSweden
constant SubLangSamiSkoltFinland (line 713) | SubLangSamiSkoltFinland
constant SubLangSamiSouthernNorway (line 715) | SubLangSamiSouthernNorway
constant SubLangSamiSouthernSweden (line 717) | SubLangSamiSouthernSweden
constant SubLangSanskritIndia (line 719) | SubLangSanskritIndia
constant SubLangScottishGaelicUnitedKingdom (line 721) | SubLangScottishGaelicUnitedKingdom
constant SubLangSerbianCyrillic (line 723) | SubLangSerbianCyrillic
constant SubLangSerbianCyrillicBosniaAndHerzegovina (line 725) | SubLangSerbianCyrillicBosniaAndHerzegovina
constant SubLangSerbianCyrillicMontenegro (line 727) | SubLangSerbianCyrillicMontenegro
constant SubLangSerbianCyrillicSerbia (line 729) | SubLangSerbianCyrillicSerbia
constant SubLangSerbianCyrillicSerbiaAndMontenegroFormer (line 731) | SubLangSerbianCyrillicSerbiaAndMontenegroFormer
constant SubLangSerbianLatin (line 733) | SubLangSerbianLatin
constant SubLangSerbianLatinBosniaAndHerzegovina (line 735) | SubLangSerbianLatinBosniaAndHerzegovina
constant SubLangSerbianLatinMontenegro (line 737) | SubLangSerbianLatinMontenegro
constant SubLangSerbianLatinSerbia (line 739) | SubLangSerbianLatinSerbia
constant SubLangSerbianLatinSerbiaAndMontenegroFormer (line 741) | SubLangSerbianLatinSerbiaAndMontenegroFormer
constant SubLangSesothoSaLeboaSouthAfrica (line 743) | SubLangSesothoSaLeboaSouthAfrica
constant SubLangSetswanaBotswana (line 745) | SubLangSetswanaBotswana
constant SubLangSetswanaSouthAfrica (line 747) | SubLangSetswanaSouthAfrica
constant SubLangSindhi (line 749) | SubLangSindhi
constant SubLangSindhiIslamicRepublicOfPakistan (line 751) | SubLangSindhiIslamicRepublicOfPakistan
constant SubLangSinhalaSriLanka (line 753) | SubLangSinhalaSriLanka
constant SubLangSlovakSlovakia (line 755) | SubLangSlovakSlovakia
constant SubLangSlovenianSlovenia (line 757) | SubLangSlovenianSlovenia
constant SubLangSomaliSomalia (line 759) | SubLangSomaliSomalia
constant SubLangSothoSouthAfrica (line 761) | SubLangSothoSouthAfrica
constant SubLangSpanishArgentina (line 763) | SubLangSpanishArgentina
constant SubLangSpanishBolivarianRepublicOfVenezuela (line 765) | SubLangSpanishBolivarianRepublicOfVenezuela
constant SubLangSpanishBolivia (line 767) | SubLangSpanishBolivia
constant SubLangSpanishChile (line 769) | SubLangSpanishChile
constant SubLangSpanishColombia (line 771) | SubLangSpanishColombia
constant SubLangSpanishCostaRica (line 773) | SubLangSpanishCostaRica
constant SubLangSpanishCuba (line 775) | SubLangSpanishCuba
constant SubLangSpanishDominicanRepublic (line 777) | SubLangSpanishDominicanRepublic
constant SubLangSpanishEcuador (line 779) | SubLangSpanishEcuador
constant SubLangSpanishElSalvador (line 781) | SubLangSpanishElSalvador
constant SubLangSpanishGuatemala (line 783) | SubLangSpanishGuatemala
constant SubLangSpanishHonduras (line 785) | SubLangSpanishHonduras
constant SubLangSpanishLatinAmerica (line 787) | SubLangSpanishLatinAmerica
constant SubLangSpanishMexico (line 789) | SubLangSpanishMexico
constant SubLangSpanishNicaragua (line 791) | SubLangSpanishNicaragua
constant SubLangSpanishPanama (line 793) | SubLangSpanishPanama
constant SubLangSpanishParaguay (line 795) | SubLangSpanishParaguay
constant SubLangSpanishPeru (line 797) | SubLangSpanishPeru
constant SubLangSpanishPuertoRico (line 799) | SubLangSpanishPuertoRico
constant SubLangSpanishSpainTraditional (line 801) | SubLangSpanishSpainTraditional
constant SubLangSpanishSpain (line 803) | SubLangSpanishSpain
constant SubLangSpanishUnitedStates (line 805) | SubLangSpanishUnitedStates
constant SubLangSpanishUruguay (line 807) | SubLangSpanishUruguay
constant SubLangSwedishFinland (line 809) | SubLangSwedishFinland
constant SubLangSwedishSweden (line 811) | SubLangSwedishSweden
constant SubLangSyriacSyria (line 813) | SubLangSyriacSyria
constant SubLangTajikCyrillic (line 815) | SubLangTajikCyrillic
constant SubLangTajikCyrillicTajikistan (line 817) | SubLangTajikCyrillicTajikistan
constant SubLangTamazightLatin (line 819) | SubLangTamazightLatin
constant SubLangTamazightLatinAlgeria (line 821) | SubLangTamazightLatinAlgeria
constant SubLangTamilIndia (line 823) | SubLangTamilIndia
constant SubLangTamilSriLanka (line 825) | SubLangTamilSriLanka
constant SubLangTatarRussia (line 827) | SubLangTatarRussia
constant SubLangTeluguIndia (line 829) | SubLangTeluguIndia
constant SubLangThaiThailand (line 831) | SubLangThaiThailand
constant SubLangTibetanPeoplesRepublicOfChina (line 833) | SubLangTibetanPeoplesRepublicOfChina
constant SubLangTigrinyaEritrea (line 835) | SubLangTigrinyaEritrea
constant SubLangTigrinyaEthiopia (line 837) | SubLangTigrinyaEthiopia
constant SubLangTsongaSouthAfrica (line 839) | SubLangTsongaSouthAfrica
constant SubLangTurkishTurkey (line 841) | SubLangTurkishTurkey
constant SubLangTurkmenTurkmenistan (line 843) | SubLangTurkmenTurkmenistan
constant SubLangUkrainianUkraine (line 845) | SubLangUkrainianUkraine
constant SubLangUpperSorbianGermany (line 847) | SubLangUpperSorbianGermany
constant SubLangUrduIndia (line 849) | SubLangUrduIndia
constant SubLangUrduIslamicRepublicOfPakistan (line 851) | SubLangUrduIslamicRepublicOfPakistan
constant SubLangUyghurPeoplesRepublicOfChina (line 853) | SubLangUyghurPeoplesRepublicOfChina
constant SubLangUzbekCyrillic (line 855) | SubLangUzbekCyrillic
constant SubLangUzbekCyrillicUzbekistan (line 857) | SubLangUzbekCyrillicUzbekistan
constant SubLangUzbekLatin (line 859) | SubLangUzbekLatin
constant SubLangUzbekLatinUzbekistan (line 861) | SubLangUzbekLatinUzbekistan
constant SubLangValencianSpain (line 863) | SubLangValencianSpain
constant SubLangVendaSouthAfrica (line 865) | SubLangVendaSouthAfrica
constant SubLangVietnameseVietnam (line 867) | SubLangVietnameseVietnam
constant SubLangWelshUnitedKingdom (line 869) | SubLangWelshUnitedKingdom
constant SubLangWolofSenegal (line 871) | SubLangWolofSenegal
constant SubLangXhosaSouthAfrica (line 873) | SubLangXhosaSouthAfrica
constant SubLangYiPeoplesRepublicOfChina (line 875) | SubLangYiPeoplesRepublicOfChina
constant SubLangYiddishWorld (line 877) | SubLangYiddishWorld
constant SubLangYorubaNigeria (line 879) | SubLangYorubaNigeria
constant SubLangZuluSouthAfrica (line 881) | SubLangZuluSouthAfrica
constant maxAllowedEntries (line 885) | maxAllowedEntries = 0x1000
constant RTCursor (line 890) | RTCursor ResourceType = iota + 1
constant RTBitmap (line 891) | RTBitmap = 2
constant RTIcon (line 892) | RTIcon = 3
constant RTMenu (line 893) | RTMenu = 4
constant RTDialog (line 894) | RTDialog = 5
constant RTString (line 895) | RTString = 6
constant RTFontDir (line 896) | RTFontDir = 7
constant RTFont (line 897) | RTFont = 8
constant RTAccelerator (line 898) | RTAccelerator = 9
constant RTRCdata (line 899) | RTRCdata = 10
constant RTMessageTable (line 900) | RTMessageTable = 11
constant RTGroupCursor (line 901) | RTGroupCursor = RTCursor + 11
constant RTGroupIcon (line 902) | RTGroupIcon = RTIcon + 11
constant RTVersion (line 903) | RTVersion = 16
constant RTDlgInclude (line 904) | RTDlgInclude = 17
constant RTPlugPlay (line 905) | RTPlugPlay = 19
constant RTVxD (line 906) | RTVxD = 20
constant RTAniCursor (line 907) | RTAniCursor = 21
constant RTAniIcon (line 908) | RTAniIcon = 22
constant RTHtml (line 909) | RTHtml = 23
constant RTManifest (line 910) | RTManifest = 24
type ImageResourceDirectory (line 916) | type ImageResourceDirectory struct
type ImageResourceDirectoryEntry (line 942) | type ImageResourceDirectoryEntry struct
type ImageResourceDataEntry (line 954) | type ImageResourceDataEntry struct
type ResourceDirectory (line 971) | type ResourceDirectory struct
type ResourceDirectoryEntry (line 980) | type ResourceDirectoryEntry struct
type ResourceDataEntry (line 1007) | type ResourceDataEntry struct
method parseResourceDataEntry (line 1019) | func (pe *File) parseResourceDataEntry(rva uint32) ImageResourceDataEntry {
method parseResourceDirectoryEntry (line 1030) | func (pe *File) parseResourceDirectoryEntry(rva uint32) *ImageResourceDi...
method doParseResourceDirectory (line 1058) | func (pe *File) doParseResourceDirectory(rva, size, baseRVA, level uint32,
method parseResourceDirectory (line 1182) | func (pe *File) parseResourceDirectory(rva, size uint32) error {
function PrettyResourceLang (line 1674) | func PrettyResourceLang(lang ResourceLang, subLang int) string {
FILE: resource_test.go
type TestRsrcDir (line 12) | type TestRsrcDir struct
function TestParseResourceDirectory (line 23) | func TestParseResourceDirectory(t *testing.T) {
function TestResourceTypeString (line 140) | func TestResourceTypeString(t *testing.T) {
function TestResourceLangString (line 168) | func TestResourceLangString(t *testing.T) {
function TestResourceSubLangString (line 197) | func TestResourceSubLangString(t *testing.T) {
function TestPrettyResourceLang (line 226) | func TestPrettyResourceLang(t *testing.T) {
FILE: richheader.go
constant DansSignature (line 16) | DansSignature = 0x536E6144
constant RichSignature (line 19) | RichSignature = "Rich"
constant AnoDansSigNotFound (line 22) | AnoDansSigNotFound = "Rich Header found, but could not locate DanS " +
constant AnoPaddingDwordNotZero (line 27) | AnoPaddingDwordNotZero = "Rich header found: 3 leading padding DWORDs " +
type CompID (line 32) | type CompID struct
type RichHeader (line 53) | type RichHeader struct
method ParseRichHeader (line 61) | func (pe *File) ParseRichHeader() error {
method RichHeaderChecksum (line 166) | func (pe *File) RichHeaderChecksum() uint32 {
method RichHeaderHash (line 195) | func (pe *File) RichHeaderHash() string {
function ProdIDtoStr (line 218) | func ProdIDtoStr(prodID uint16) string {
function ProdIDtoVSversion (line 503) | func ProdIDtoVSversion(prodID uint16) string {
FILE: richheader_test.go
type TestRichHeader (line 12) | type TestRichHeader struct
function TestParseRichHeader (line 20) | func TestParseRichHeader(t *testing.T) {
function TestRichHeaderHash (line 145) | func TestRichHeaderHash(t *testing.T) {
FILE: scripts/extract-rsrc-lang.py
class Language (line 5) | class Language:
method __str__ (line 12) | def __str__(self) -> str:
function sanitize_lang (line 15) | def sanitize_lang(language):
function read_lang_ids (line 28) | def read_lang_ids(filename):
function parse_txt_file (line 40) | def parse_txt_file(filename, lang_ids):
function generate_go_code (line 88) | def generate_go_code(languages : list[Language]):
function generate_lang_string (line 108) | def generate_lang_string(languages : list[Language]):
function generate_sub_lang_string (line 116) | def generate_sub_lang_string(languages : list[Language]):
function generate_lang_sub_lang_map_string (line 124) | def generate_lang_sub_lang_map_string(languages : list[Language]):
function write_generated_code (line 142) | def write_generated_code(code, filename):
FILE: section.go
constant ImageSectionReserved1 (line 16) | ImageSectionReserved1 = 0x00000000
constant ImageSectionReserved2 (line 19) | ImageSectionReserved2 = 0x00000001
constant ImageSectionReserved3 (line 22) | ImageSectionReserved3 = 0x00000002
constant ImageSectionReserved4 (line 25) | ImageSectionReserved4 = 0x00000004
constant ImageSectionTypeNoPad (line 30) | ImageSectionTypeNoPad = 0x00000008
constant ImageSectionReserved5 (line 33) | ImageSectionReserved5 = 0x00000010
constant ImageSectionCntCode (line 36) | ImageSectionCntCode = 0x00000020
constant ImageSectionCntInitializedData (line 40) | ImageSectionCntInitializedData = 0x00000040
constant ImageSectionCntUninitializedData (line 44) | ImageSectionCntUninitializedData = 0x00000080
constant ImageSectionLnkOther (line 47) | ImageSectionLnkOther = 0x00000100
constant ImageSectionLnkInfo (line 52) | ImageSectionLnkInfo = 0x00000200
constant ImageSectionReserved6 (line 55) | ImageSectionReserved6 = 0x00000400
constant ImageSectionLnkRemove (line 59) | ImageSectionLnkRemove = 0x00000800
constant ImageSectionLnkCOMDAT (line 64) | ImageSectionLnkCOMDAT = 0x00001000
constant ImageSectionGpRel (line 68) | ImageSectionGpRel = 0x00008000
constant ImageSectionMemPurgeable (line 71) | ImageSectionMemPurgeable = 0x00020000
constant ImageSectionMem16Bit (line 74) | ImageSectionMem16Bit = 0x00020000
constant ImageSectionMemLocked (line 77) | ImageSectionMemLocked = 0x00040000
constant ImageSectionMemPreload (line 80) | ImageSectionMemPreload = 0x00080000
constant ImageSectionAlign1Bytes (line 84) | ImageSectionAlign1Bytes = 0x00100000
constant ImageSectionAlign2Bytes (line 88) | ImageSectionAlign2Bytes = 0x00200000
constant ImageSectionAlign4Bytes (line 92) | ImageSectionAlign4Bytes = 0x00300000
constant ImageSectionAlign8Bytes (line 96) | ImageSectionAlign8Bytes = 0x00400000
constant ImageSectionAlign16Bytes (line 100) | ImageSectionAlign16Bytes = 0x00500000
constant ImageSectionAlign32Bytes (line 104) | ImageSectionAlign32Bytes = 0x00600000
constant ImageSectionAlign64Bytes (line 108) | ImageSectionAlign64Bytes = 0x00700000
constant ImageSectionAlign128Bytes (line 112) | ImageSectionAlign128Bytes = 0x00800000
constant ImageSectionAlign256Bytes (line 116) | ImageSectionAlign256Bytes = 0x00900000
constant ImageSectionAlign512Bytes (line 120) | ImageSectionAlign512Bytes = 0x00A00000
constant ImageSectionAlign1024Bytes (line 124) | ImageSectionAlign1024Bytes = 0x00B00000
constant ImageSectionAlign2048Bytes (line 128) | ImageSectionAlign2048Bytes = 0x00C00000
constant ImageSectionAlign4096Bytes (line 132) | ImageSectionAlign4096Bytes = 0x00D00000
constant ImageSectionAlign8192Bytes (line 136) | ImageSectionAlign8192Bytes = 0x00E00000
constant ImageSectionLnkNRelocOvfl (line 140) | ImageSectionLnkNRelocOvfl = 0x01000000
constant ImageSectionMemDiscardable (line 143) | ImageSectionMemDiscardable = 0x02000000
constant ImageSectionMemNotCached (line 146) | ImageSectionMemNotCached = 0x04000000
constant ImageSectionMemNotPaged (line 149) | ImageSectionMemNotPaged = 0x08000000
constant ImageSectionMemShared (line 152) | ImageSectionMemShared = 0x10000000
constant ImageSectionMemExecute (line 155) | ImageSectionMemExecute = 0x20000000
constant ImageSectionMemRead (line 158) | ImageSectionMemRead = 0x40000000
constant ImageSectionMemWrite (line 161) | ImageSectionMemWrite = 0x80000000
type ImageSectionHeader (line 169) | type ImageSectionHeader struct
type Section (line 231) | type Section struct
method String (line 377) | func (section *Section) String() string {
method NextHeaderAddr (line 382) | func (section *Section) NextHeaderAddr(pe *File) uint32 {
method Contains (line 397) | func (section *Section) Contains(rva uint32, pe *File) bool {
method Data (line 426) | func (section *Section) Data(start, length uint32, pe *File) []byte {
method CalculateEntropy (line 467) | func (section *Section) CalculateEntropy(pe *File) float64 {
method PrettySectionFlags (line 514) | func (section *Section) PrettySectionFlags() []string {
method ParseSectionHeader (line 244) | func (pe *File) ParseSectionHeader() (err error) {
type byVirtualAddress (line 495) | type byVirtualAddress
method Len (line 497) | func (s byVirtualAddress) Len() int { return len(s) }
method Swap (line 498) | func (s byVirtualAddress) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
method Less (line 499) | func (s byVirtualAddress) Less(i, j int) bool {
type byPointerToRawData (line 504) | type byPointerToRawData
method Len (line 506) | func (s byPointerToRawData) Len() int { return len(s) }
method Swap (line 507) | func (s byPointerToRawData) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
method Less (line 508) | func (s byPointerToRawData) Less(i, j int) bool {
FILE: section_test.go
type TestSection (line 13) | type TestSection struct
function TestParseSectionHeaders (line 22) | func TestParseSectionHeaders(t *testing.T) {
FILE: security.go
constant WinCertRevision1_0 (line 37) | WinCertRevision1_0 = 0x0100
constant WinCertRevision2_0 (line 41) | WinCertRevision2_0 = 0x0200
constant WinCertTypeX509 (line 49) | WinCertTypeX509 = 0x0001
constant WinCertTypePKCSSignedData (line 52) | WinCertTypePKCSSignedData = 0x0002
constant WinCertTypeReserved1 (line 55) | WinCertTypeReserved1 = 0x0003
constant WinCertTypeTSStackSigned (line 58) | WinCertTypeTSStackSigned = 0x0004
type CertificateSection (line 73) | type CertificateSection struct
type Certificate (line 92) | type Certificate struct
type WinCertificate (line 114) | type WinCertificate struct
type CertInfo (line 127) | type CertInfo struct
type RelRange (line 159) | type RelRange struct
type byStart (line 164) | type byStart
method Len (line 166) | func (s byStart) Len() int { return len(s) }
method Swap (line 167) | func (s byStart) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
method Less (line 168) | func (s byStart) Less(i, j int) bool {
type Range (line 172) | type Range struct
method parseLocations (line 177) | func (pe *File) parseLocations() (map[string]*RelRange, error) {
method Authentihash (line 279) | func (pe *File) Authentihash() []byte {
method AuthentihashExt (line 292) | func (pe *File) AuthentihashExt(hashers ...hash.Hash) [][]byte {
method parseSecurityDirectory (line 344) | func (pe *File) parseSecurityDirectory(rva, size uint32) error {
function loadSystemRoots (line 476) | func loadSystemRoots() (*x509.CertPool, error) {
type SpcIndirectDataContent (line 534) | type SpcIndirectDataContent struct
type SpcAttributeTypeAndOptionalValue (line 539) | type SpcAttributeTypeAndOptionalValue struct
type SpcPeImageData (line 544) | type SpcPeImageData struct
type DigestInfo (line 549) | type DigestInfo struct
function parseHashAlgorithm (line 555) | func parseHashAlgorithm(identifier pkix.AlgorithmIdentifier) (crypto.Has...
type AuthenticodeContent (line 584) | type AuthenticodeContent struct
function parseAuthenticodeContent (line 590) | func parseAuthenticodeContent(content []byte) (AuthenticodeContent, erro...
function formatPkixName (line 611) | func formatPkixName(name pkix.Name) string {
FILE: security_linux_mac.go
function hideWindow (line 8) | func hideWindow(cmd *exec.Cmd) {
FILE: security_test.go
type TestSecurityEntry (line 17) | type TestSecurityEntry struct
function TestParseSecurityDirectory (line 23) | func TestParseSecurityDirectory(t *testing.T) {
function TestAuthentihash (line 212) | func TestAuthentihash(t *testing.T) {
FILE: security_windows.go
function hideWindow (line 11) | func hideWindow(cmd *exec.Cmd) {
FILE: symbol.go
constant MaxDefaultCOFFSymbolsCount (line 20) | MaxDefaultCOFFSymbolsCount = 0x10000
constant MaxCOFFSymStrLength (line 24) | MaxCOFFSymStrLength = 0x50
constant ImageSymTypeNull (line 32) | ImageSymTypeNull = 0
constant ImageSymTypeVoid (line 35) | ImageSymTypeVoid = 1
constant ImageSymTypeChar (line 38) | ImageSymTypeChar = 2
constant ImageSymTypeShort (line 41) | ImageSymTypeShort = 3
constant ImageSymTypeInt (line 45) | ImageSymTypeInt = 4
constant ImageSymTypeLong (line 48) | ImageSymTypeLong = 5
constant ImageSymTypeFloat (line 51) | ImageSymTypeFloat = 6
constant ImageSymTypeDouble (line 54) | ImageSymTypeDouble = 7
constant ImageSymTypeStruct (line 57) | ImageSymTypeStruct = 8
constant ImageSymTypeUnion (line 60) | ImageSymTypeUnion = 9
constant ImageSymTypeEnum (line 63) | ImageSymTypeEnum = 10
constant ImageSymTypeMoe (line 66) | ImageSymTypeMoe = 11
constant ImageSymTypeByte (line 69) | ImageSymTypeByte = 12
constant ImageSymTypeWord (line 72) | ImageSymTypeWord = 13
constant ImageSymTypeUint (line 76) | ImageSymTypeUint = 14
constant ImageSymTypeDword (line 79) | ImageSymTypeDword = 15
constant ImageSymClassEndOfFunction (line 87) | ImageSymClassEndOfFunction = 0xff
constant ImageSymClassNull (line 90) | ImageSymClassNull = 0
constant ImageSymClassAutomatic (line 94) | ImageSymClassAutomatic = 1
constant ImageSymClassExternal (line 100) | ImageSymClassExternal = 2
constant ImageSymClassStatic (line 105) | ImageSymClassStatic = 3
constant ImageSymClassRegister (line 109) | ImageSymClassRegister = 4
constant ImageSymClassExternalDef (line 112) | ImageSymClassExternalDef = 5
constant ImageSymClassLabel (line 117) | ImageSymClassLabel = 6
constant ImageSymClassUndefinedLabel (line 121) | ImageSymClassUndefinedLabel = 7
constant ImageSymClassMemberOfStruct (line 125) | ImageSymClassMemberOfStruct = 8
constant ImageSymClassArgument (line 129) | ImageSymClassArgument = 9
constant ImageSymClassStructTag (line 132) | ImageSymClassStructTag = 10
constant ImageSymClassMemberOfUnion (line 136) | ImageSymClassMemberOfUnion = 11
constant ImageSymClassUnionTag (line 139) | ImageSymClassUnionTag = 12
constant ImageSymClassTypeDefinition (line 142) | ImageSymClassTypeDefinition = 13
constant ImageSymClassUndefinedStatic (line 145) | ImageSymClassUndefinedStatic = 14
constant ImageSymClassEnumTag (line 148) | ImageSymClassEnumTag = 15
constant ImageSymClassMemberOfEnum (line 152) | ImageSymClassMemberOfEnum = 16
constant ImageSymClassRegisterParam (line 155) | ImageSymClassRegisterParam = 17
constant ImageSymClassBitField (line 159) | ImageSymClassBitField = 18
constant ImageSymClassBlock (line 164) | ImageSymClassBlock = 100
constant ImageSymClassFunction (line 172) | ImageSymClassFunction = 101
constant ImageSymClassEndOfStruct (line 175) | ImageSymClassEndOfStruct = 102
constant ImageSymClassFile (line 180) | ImageSymClassFile = 103
constant ImageSymClassSsection (line 184) | ImageSymClassSsection = 104
constant ImageSymClassWeakExternal (line 188) | ImageSymClassWeakExternal = 24
constant ImageSymClassClrToken (line 193) | ImageSymClassClrToken = 25
constant ImageSymUndefined (line 203) | ImageSymUndefined = 0
constant ImageSymAbsolute (line 207) | ImageSymAbsolute = -1
constant ImageSymDebug (line 212) | ImageSymDebug = -2
type COFFSymbol (line 230) | type COFFSymbol struct
method String (line 381) | func (symbol *COFFSymbol) String(pe *File) (string, error) {
method SectionNumberName (line 411) | func (symbol *COFFSymbol) SectionNumberName(pe *File) string {
type COFF (line 267) | type COFF struct
method ParseCOFFSymbolTable (line 282) | func (pe *File) ParseCOFFSymbolTable() error {
method COFFStringTable (line 325) | func (pe *File) COFFStringTable() error {
method PrettyCOFFTypeRepresentation (line 435) | func (pe *File) PrettyCOFFTypeRepresentation(k uint16) string {
FILE: symbol_test.go
type TestCOFFSymbol (line 9) | type TestCOFFSymbol struct
function TestParseCOFFSymbolTable (line 78) | func TestParseCOFFSymbolTable(t *testing.T) {
FILE: tls.go
type TLSDirectoryCharacteristicsType (line 13) | type TLSDirectoryCharacteristicsType
method String (line 164) | func (characteristics TLSDirectoryCharacteristicsType) String() string {
type TLSDirectory (line 16) | type TLSDirectory struct
type ImageTLSDirectory32 (line 27) | type ImageTLSDirectory32 struct
type ImageTLSDirectory64 (line 62) | type ImageTLSDirectory64 struct
method parseTLSDirectory (line 99) | func (pe *File) parseTLSDirectory(rva, size uint32) error {
FILE: tls_test.go
function TestParseTLSDirectory (line 12) | func TestParseTLSDirectory(t *testing.T) {
function TestTLSDirectoryCharacteristics (line 85) | func TestTLSDirectoryCharacteristics(t *testing.T) {
FILE: version.go
constant VersionResourceType (line 15) | VersionResourceType = 16
constant VsVersionInfoString (line 18) | VsVersionInfoString = "VS_VERSION_INFO"
constant VsFileInfoSignature (line 21) | VsFileInfoSignature uint32 = 0xFEEF04BD
constant StringFileInfoString (line 24) | StringFileInfoString = "StringFileInfo"
constant VarFileInfoString (line 26) | VarFileInfoString = "VarFileInfo"
constant VsVersionInfoStringLength (line 29) | VsVersionInfoStringLength uint32 = 6
constant StringFileInfoLength (line 31) | StringFileInfoLength uint32 = 6
constant StringTableLength (line 33) | StringTableLength uint32 = 6
constant StringLength (line 35) | StringLength uint32 = 6
constant LangIDLength (line 38) | LangIDLength uint32 = 8*2 + 1
type VsVersionInfo (line 44) | type VsVersionInfo struct
method parseVersionInfo (line 60) | func (pe *File) parseVersionInfo(e ResourceDirectoryEntry) (*VsVersionIn...
type VsFixedFileInfo (line 86) | type VsFixedFileInfo struct
method Size (line 127) | func (f *VsFixedFileInfo) Size() uint32 { return uint32(binary.Size(f)) }
method GetStringFileInfoOffset (line 129) | func (f *VsFixedFileInfo) GetStringFileInfoOffset(e ResourceDirectoryE...
method GetOffset (line 133) | func (f *VsFixedFileInfo) GetOffset(e ResourceDirectoryEntry, pe *File...
method parseFixedFileInfo (line 139) | func (pe *File) parseFixedFileInfo(e ResourceDirectoryEntry) (*VsFixedFi...
type StringFileInfo (line 158) | type StringFileInfo struct
method GetStringTableOffset (line 164) | func (s *StringFileInfo) GetStringTableOffset(offset uint32) uint32 {
method GetOffset (line 168) | func (s *StringFileInfo) GetOffset(rva uint32, e ResourceDirectoryEntr...
method parseStringFileInfo (line 173) | func (pe *File) parseStringFileInfo(rva uint32, e ResourceDirectoryEntry...
type StringTable (line 194) | type StringTable struct
method GetStringOffset (line 200) | func (s *StringTable) GetStringOffset(offset uint32, e ResourceDirecto...
method GetOffset (line 204) | func (s *StringTable) GetOffset(rva uint32, e ResourceDirectoryEntry, ...
method parseStringTable (line 209) | func (pe *File) parseStringTable(rva uint32, e ResourceDirectoryEntry) (...
type String (line 243) | type String struct
method GetOffset (line 249) | func (s *String) GetOffset(rva uint32, e ResourceDirectoryEntry, pe *F...
method getOffsetAndPadding (line 257) | func (s *String) getOffsetAndPadding(rva uint32, e ResourceDirectoryEn...
method parseString (line 263) | func (pe *File) parseString(rva uint32, e ResourceDirectoryEntry) (strin...
method ParseVersionResources (line 305) | func (pe *File) ParseVersionResources() (map[string]string, error) {
method parseVersionEntry (line 330) | func (pe *File) parseVersionEntry(e ResourceDirectoryEntry, vers map[str...
method ParseVersionResourcesForEntries (line 396) | func (pe *File) ParseVersionResourcesForEntries() ([]map[string]string, ...
FILE: version_test.go
function TestParseVersionResources (line 53) | func TestParseVersionResources(t *testing.T) {
Condensed preview — 91 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (864K chars).
[
{
"path": ".editorconfig",
"chars": 354,
"preview": "; https://editorconfig.org/\n\nroot = true\n\n[*]\ninsert_final_newline = true\ncharset = utf-8\ntrim_trailing_whitespace = tru"
},
{
"path": ".gitattributes",
"chars": 639,
"preview": "# Treat all files in the Go repo as binary, with no git magic updating\n# line endings. This produces predictable results"
},
{
"path": ".github/FUNDING.YML",
"chars": 22,
"preview": "github: LordNoteworthy"
},
{
"path": ".github/workflows/ci.yaml",
"chars": 1365,
"preview": "name: Build & Test\n\non: [push]\n\njobs:\n test:\n name: Build & Test\n strategy:\n fail-fast: false\n matrix:\n"
},
{
"path": ".gitignore",
"chars": 405,
"preview": "# Binaries for programs and plugins\n*.exe\n*.exe~\n*.dll\n*.so\n*.dylib\n\n# Test binary, built with `go test -c`\n*.test\n\n# Ou"
},
{
"path": "CHANGELOG.md",
"chars": 8476,
"preview": "# Changelog\n\nAll notable changes to this project will be documented in this file.\n\nThe format is based on [Keep a Change"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 3217,
"preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
},
{
"path": "LICENSE",
"chars": 1065,
"preview": "MIT License\n\nCopyright (c) 2021 Saferwall\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
},
{
"path": "README.md",
"chars": 9816,
"preview": "<a href=\"https://saferwall.com\" target=\"_blank\" rel=\"noopener noreferrer\"><img align=\"right\" width=\"300\" src=\".github/as"
},
{
"path": "anomaly.go",
"chars": 9150,
"preview": "// Copyright 2021 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "anomaly_test.go",
"chars": 1265,
"preview": "// Copyright 2021 Saferwall. All rights reserved.\r\n// Use of this source code is governed by Apache v2 license\r\n// licen"
},
{
"path": "arch.go",
"chars": 380,
"preview": "// Copyright 2022 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "boundimports.go",
"chars": 5412,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "boundimports_test.go",
"chars": 2799,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\r\n// Use of this source code is governed by Apache v2 license\r\n// licen"
},
{
"path": "cmd/dump.go",
"chars": 38742,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "cmd/main.go",
"chars": 4419,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "cmd/size.go",
"chars": 4060,
"preview": "package main\r\n\r\nimport (\r\n\t\"fmt\"\r\n\t\"strconv\"\r\n\t\"strings\"\r\n)\r\n\r\n// See: http://en.wikipedia.org/wiki/Binary_prefix\r\nconst"
},
{
"path": "cmd/size_test.go",
"chars": 8356,
"preview": "package main\r\n\r\nimport (\r\n\t\"fmt\"\r\n\t\"reflect\"\r\n\t\"runtime\"\r\n\t\"strings\"\r\n\t\"testing\"\r\n)\r\n\r\nfunc ExampleBytesSize() {\r\n\tfmt.P"
},
{
"path": "debug.go",
"chars": 25355,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "debug_test.go",
"chars": 16929,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "delayimports.go",
"chars": 5648,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "delayimports_test.go",
"chars": 2879,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\r\n// Use of this source code is governed by Apache v2 license\r\n// licen"
},
{
"path": "dosheader.go",
"chars": 3134,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "dosheader_test.go",
"chars": 2227,
"preview": "// Copyright 2022 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "dotnet.go",
"chars": 27669,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "dotnet_helper.go",
"chars": 3685,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "dotnet_metadata_tables.go",
"chars": 41741,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "dotnet_test.go",
"chars": 20861,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "exception.go",
"chars": 21226,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "exception_test.go",
"chars": 3668,
"preview": "// Copyright 2021 Saferwall. All rights reserved.\r\n// Use of this source code is governed by Apache v2 license\r\n// licen"
},
{
"path": "exports.go",
"chars": 10560,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "exports_test.go",
"chars": 4178,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\r\n// Use of this source code is governed by Apache v2 license\r\n// licen"
},
{
"path": "file.go",
"chars": 12067,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "file_test.go",
"chars": 3155,
"preview": "// Copyright 2021 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "globalptr.go",
"chars": 1130,
"preview": "// Copyright 2022 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "go.mod",
"chars": 151,
"preview": "module github.com/saferwall/pe\n\ngo 1.15\n\nrequire (\n\tgithub.com/ayoubfaouzi/pkcs7 v0.2.3\n\tgithub.com/edsrzf/mmap-go v1.1."
},
{
"path": "go.sum",
"chars": 6406,
"preview": "github.com/ayoubfaouzi/pkcs7 v0.2.3 h1:XGCYHteXgclHnNlPdCF8aFyoUKwP9VhLQp+VX+hBZ3U=\ngithub.com/ayoubfaouzi/pkcs7 v0.2.3/"
},
{
"path": "helper.go",
"chars": 20168,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "helper_test.go",
"chars": 1994,
"preview": "// Copyright 2021 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "iat.go",
"chars": 1874,
"preview": "// Copyright 2022 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "imports.go",
"chars": 25164,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "imports_test.go",
"chars": 4246,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "loadconfig.go",
"chars": 57033,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "loadconfig_test.go",
"chars": 29890,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\r\n// Use of this source code is governed by Apache v2 license\r\n// licen"
},
{
"path": "log/README.md",
"chars": 1026,
"preview": "# Logger\n\nThis code was taken from the go microservice framework [kratos](https://github.com/go-kratos/kratos).\n\n## Usag"
},
{
"path": "log/filter.go",
"chars": 2097,
"preview": "package log\n\n// FilterOption is filter option.\ntype FilterOption func(*Filter)\n\nconst fuzzyStr = \"***\"\n\n// FilterLevel w"
},
{
"path": "log/filter_test.go",
"chars": 3512,
"preview": "package log\n\nimport (\n\t\"bytes\"\n\t\"io\"\n\t\"testing\"\n)\n\nfunc TestFilterAll(t *testing.T) {\n\tlogger := With(DefaultLogger, \"ts"
},
{
"path": "log/global.go",
"chars": 2650,
"preview": "package log\n\nimport (\n\t\"sync\"\n)\n\n// globalLogger is designed as a global logger in current process.\nvar global = &logger"
},
{
"path": "log/global_test.go",
"chars": 1895,
"preview": "package log\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"os\"\n\t\"strings\"\n\t\"testing\"\n)\n\nfunc TestGlobalLog(t *testing.T) {\n\tbuffer := &byte"
},
{
"path": "log/helper.go",
"chars": 3290,
"preview": "package log\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"os\"\n)\n\n// DefaultMessageKey default message key.\nvar DefaultMessageKey = \"msg\""
},
{
"path": "log/helper_test.go",
"chars": 1746,
"preview": "package log\n\nimport (\n\t\"context\"\n\t\"io\"\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestHelper(t *testing.T) {\n\tlogger := With(DefaultLogger"
},
{
"path": "log/level.go",
"chars": 970,
"preview": "package log\n\nimport \"strings\"\n\n// Level is a logger level.\ntype Level int8\n\n// LevelKey is logger level key.\nconst Level"
},
{
"path": "log/level_test.go",
"chars": 1375,
"preview": "package log\n\nimport \"testing\"\n\nfunc TestLevel_String(t *testing.T) {\n\ttests := []struct {\n\t\tname string\n\t\tl Level\n\t\tw"
},
{
"path": "log/log.go",
"chars": 1590,
"preview": "package log\n\nimport (\n\t\"context\"\n\t\"log\"\n)\n\n// DefaultLogger is default logger.\nvar DefaultLogger = NewStdLogger(log.Writ"
},
{
"path": "log/log_test.go",
"chars": 528,
"preview": "package log\n\nimport (\n\t\"context\"\n\t\"os\"\n\t\"testing\"\n)\n\nfunc TestInfo(t *testing.T) {\n\tlogger := DefaultLogger\n\tlogger = Wi"
},
{
"path": "log/std.go",
"chars": 871,
"preview": "package log\n\nimport (\n\t\"bytes\"\n\t\"fmt\"\n\t\"io\"\n\t\"log\"\n\t\"sync\"\n)\n\nvar _ Logger = (*stdLogger)(nil)\n\ntype stdLogger struct {\n"
},
{
"path": "log/std_test.go",
"chars": 452,
"preview": "package log\n\nimport \"testing\"\n\nfunc TestStdLogger(t *testing.T) {\n\tlogger := DefaultLogger\n\tlogger = With(logger, \"calle"
},
{
"path": "log/value.go",
"chars": 1618,
"preview": "package log\n\nimport (\n\t\"context\"\n\t\"runtime\"\n\t\"strconv\"\n\t\"strings\"\n\t\"time\"\n)\n\nvar (\n\tdefaultDepth = 3\n\t// DefaultCaller i"
},
{
"path": "log/value_test.go",
"chars": 637,
"preview": "package log\n\nimport (\n\t\"context\"\n\t\"testing\"\n)\n\nfunc TestValue(t *testing.T) {\n\tlogger := DefaultLogger\n\tlogger = With(lo"
},
{
"path": "ntheader.go",
"chars": 25005,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "ntheader_test.go",
"chars": 3332,
"preview": "// Copyright 2021 Saferwall. All rights reserved.\r\n// Use of this source code is governed by Apache v2 license\r\n// licen"
},
{
"path": "ordlookup.go",
"chars": 13129,
"preview": "// Copyright 2021 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "overlay.go",
"chars": 992,
"preview": "// Copyright 2022 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "overlay_test.go",
"chars": 1305,
"preview": "package pe\n\nimport (\n\t\"crypto/md5\"\n\t\"encoding/hex\"\n\t\"testing\"\n)\n\ntype TestOverlay struct {\n\toverlayOffset int64\n\toverlay"
},
{
"path": "pe.go",
"chars": 11089,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "reloc.go",
"chars": 10512,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "reloc_test.go",
"chars": 7189,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "resource.go",
"chars": 79479,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "resource_test.go",
"chars": 5861,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "richheader.go",
"chars": 15697,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "richheader_test.go",
"chars": 4210,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "scripts/extract-rsrc-lang.py",
"chars": 5466,
"preview": "# Text file containing languages and sub-languages extracted from:\r\n# Language Identifier Constants and Strings for Micr"
},
{
"path": "scripts/ms-lcid.txt",
"chars": 25250,
"preview": "Afar 0x1000 aa\r\nAfar Djibouti 0x1000 aa-DJ\r\nAfar Eritrea 0x1000 aa-ER\r\nAfar Ethiopia 0x1000 aa-ET\r\nAfrikaans 0x0036 af\r\n"
},
{
"path": "section.go",
"chars": 20170,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "section_test.go",
"chars": 2370,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "security.go",
"chars": 19890,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "security_linux_mac.go",
"chars": 114,
"preview": "//go:build !windows\r\n// +build !windows\r\n\r\npackage pe\r\n\r\nimport \"os/exec\"\r\n\r\nfunc hideWindow(cmd *exec.Cmd) {\r\n}\r\n"
},
{
"path": "security_test.go",
"chars": 8435,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "security_windows.go",
"chars": 190,
"preview": "//go:build windows\r\n// +build windows\r\n\r\npackage pe\r\n\r\nimport (\r\n\t\"os/exec\"\r\n\t\"syscall\"\r\n)\r\n\r\nfunc hideWindow(cmd *exec."
},
{
"path": "staticcheck.conf",
"chars": 48,
"preview": "checks = [\"all\", \"-ST1000\", \"-U1000\", \"-SA1019\"]"
},
{
"path": "symbol.go",
"chars": 15266,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "symbol_test.go",
"chars": 3896,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "tls.go",
"chars": 6977,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "tls_test.go",
"chars": 2753,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\r\n// Use of this source code is governed by Apache v2 license\r\n// licen"
},
{
"path": "version.go",
"chars": 14830,
"preview": "// Copyright 2018 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
},
{
"path": "version_test.go",
"chars": 3335,
"preview": "// Copyright 2021 Saferwall. All rights reserved.\n// Use of this source code is governed by Apache v2 license\n// license"
}
]
// ... and 5 more files (download for full content)
About this extraction
This page contains the full source code of the saferwall/pe GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 91 files (765.7 KB), approximately 233.6k tokens, and a symbol index with 1452 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.