mirror of
https://github.com/wader/fq.git
synced 2024-10-27 04:09:37 +03:00
Compare commits
28 Commits
d5d35907c7
...
3f2aa75ec8
Author | SHA1 | Date | |
---|---|---|---|
|
3f2aa75ec8 | ||
|
9874077e20 | ||
|
3966035eba | ||
|
9db82260e5 | ||
|
52eaf10de2 | ||
|
a1fb076248 | ||
|
6caa7fa78b | ||
|
f5471adb4f | ||
|
7f42d64e44 | ||
|
58f4f61ac5 | ||
|
5bfe27803b | ||
|
30929cde85 | ||
|
41988023bc | ||
|
f4d9428855 | ||
|
2bc6c768c7 | ||
|
b3e5be095b | ||
|
6383626aa3 | ||
|
71476743a0 | ||
|
19bd2fbd7c | ||
|
c55e10667c | ||
|
292bd02397 | ||
|
bbdd43f5c8 | ||
|
35a8eddf04 | ||
|
8df50bf62f | ||
|
1ff5a3fadf | ||
|
7566fd9307 | ||
|
f7cbf84469 | ||
|
ab09d3ce6f |
6
.github/workflows/ci.yml
vendored
6
.github/workflows/ci.yml
vendored
@ -7,7 +7,7 @@ on:
|
|||||||
pull_request:
|
pull_request:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
GOLANGCILINT_VERSION: "1.59.0"
|
GOLANGCILINT_VERSION: "1.59.1"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
@ -15,7 +15,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/setup-go@v3
|
- uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: "1.22.3"
|
go-version: "1.22.4"
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: golangci/golangci-lint-action@v3
|
- uses: golangci/golangci-lint-action@v3
|
||||||
with:
|
with:
|
||||||
@ -47,7 +47,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-go@v3
|
- uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: "1.22.3"
|
go-version: "1.22.4"
|
||||||
- name: Test
|
- name: Test
|
||||||
env:
|
env:
|
||||||
GOARCH: ${{ matrix.goarch }}
|
GOARCH: ${{ matrix.goarch }}
|
||||||
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
|||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-go@v3
|
- uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: "1.22.3"
|
go-version: "1.22.4"
|
||||||
- uses: goreleaser/goreleaser-action@v5
|
- uses: goreleaser/goreleaser-action@v5
|
||||||
with:
|
with:
|
||||||
distribution: goreleaser
|
distribution: goreleaser
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
# bump: docker-golang /FROM golang:([\d.]+)/ docker:golang|^1
|
# bump: docker-golang /FROM golang:([\d.]+)/ docker:golang|^1
|
||||||
FROM golang:1.22.3-bookworm AS base
|
FROM golang:1.22.4-bookworm AS base
|
||||||
|
|
||||||
# expect is used to test cli
|
# expect is used to test cli
|
||||||
RUN \
|
RUN \
|
||||||
|
2
Makefile
2
Makefile
@ -61,7 +61,7 @@ gogenerate: always
|
|||||||
lint: always
|
lint: always
|
||||||
# bump: make-golangci-lint /golangci-lint@v([\d.]+)/ git:https://github.com/golangci/golangci-lint.git|^1
|
# bump: make-golangci-lint /golangci-lint@v([\d.]+)/ git:https://github.com/golangci/golangci-lint.git|^1
|
||||||
# bump: make-golangci-lint link "Release notes" https://github.com/golangci/golangci-lint/releases/tag/v$LATEST
|
# bump: make-golangci-lint link "Release notes" https://github.com/golangci/golangci-lint/releases/tag/v$LATEST
|
||||||
go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.59.0 run
|
go run github.com/golangci/golangci-lint/cmd/golangci-lint@v1.59.1 run
|
||||||
|
|
||||||
depgraph.svg: always
|
depgraph.svg: always
|
||||||
go run github.com/kisielk/godepgraph@latest github.com/wader/fq | dot -Tsvg -o godepgraph.svg
|
go run github.com/kisielk/godepgraph@latest github.com/wader/fq | dot -Tsvg -o godepgraph.svg
|
||||||
|
@ -138,6 +138,7 @@ prores_frame,
|
|||||||
[protobuf](doc/formats.md#protobuf),
|
[protobuf](doc/formats.md#protobuf),
|
||||||
protobuf_widevine,
|
protobuf_widevine,
|
||||||
pssh_playready,
|
pssh_playready,
|
||||||
|
[pyrdp](doc/formats.md#pyrdp),
|
||||||
[rtmp](doc/formats.md#rtmp),
|
[rtmp](doc/formats.md#rtmp),
|
||||||
sll2_packet,
|
sll2_packet,
|
||||||
sll_packet,
|
sll_packet,
|
||||||
|
@ -110,6 +110,7 @@
|
|||||||
|[`protobuf`](#protobuf) |Protobuf |<sub></sub>|
|
|[`protobuf`](#protobuf) |Protobuf |<sub></sub>|
|
||||||
|`protobuf_widevine` |Widevine protobuf |<sub>`protobuf`</sub>|
|
|`protobuf_widevine` |Widevine protobuf |<sub>`protobuf`</sub>|
|
||||||
|`pssh_playready` |PlayReady PSSH |<sub></sub>|
|
|`pssh_playready` |PlayReady PSSH |<sub></sub>|
|
||||||
|
|[`pyrdp`](#pyrdp) |PyRDP Replay Files |<sub></sub>|
|
||||||
|[`rtmp`](#rtmp) |Real-Time Messaging Protocol |<sub>`amf0` `mpeg_asc`</sub>|
|
|[`rtmp`](#rtmp) |Real-Time Messaging Protocol |<sub>`amf0` `mpeg_asc`</sub>|
|
||||||
|`sll2_packet` |Linux cooked capture encapsulation v2 |<sub>`inet_packet`</sub>|
|
|`sll2_packet` |Linux cooked capture encapsulation v2 |<sub>`inet_packet`</sub>|
|
||||||
|`sll_packet` |Linux cooked capture encapsulation |<sub>`inet_packet`</sub>|
|
|`sll_packet` |Linux cooked capture encapsulation |<sub>`inet_packet`</sub>|
|
||||||
@ -1195,6 +1196,16 @@ $ fq -d protobuf '.fields[6].wire_value | protobuf | d' file
|
|||||||
### References
|
### References
|
||||||
- https://developers.google.com/protocol-buffers/docs/encoding
|
- https://developers.google.com/protocol-buffers/docs/encoding
|
||||||
|
|
||||||
|
## pyrdp
|
||||||
|
PyRDP Replay Files.
|
||||||
|
|
||||||
|
### Authors
|
||||||
|
- Olivier Bilodeau <olivier.bilodeau@flare.io>, Maintainer
|
||||||
|
- Lisandro Ubiedo, Author
|
||||||
|
|
||||||
|
### References
|
||||||
|
- https://github.com/GoSecure/pyrdp
|
||||||
|
|
||||||
## rtmp
|
## rtmp
|
||||||
Real-Time Messaging Protocol.
|
Real-Time Messaging Protocol.
|
||||||
|
|
||||||
|
@ -153,6 +153,7 @@ prores_frame Apple ProRes frame
|
|||||||
protobuf Protobuf
|
protobuf Protobuf
|
||||||
protobuf_widevine Widevine protobuf
|
protobuf_widevine Widevine protobuf
|
||||||
pssh_playready PlayReady PSSH
|
pssh_playready PlayReady PSSH
|
||||||
|
pyrdp PyRDP Replay Files
|
||||||
rtmp Real-Time Messaging Protocol
|
rtmp Real-Time Messaging Protocol
|
||||||
sll2_packet Linux cooked capture encapsulation v2
|
sll2_packet Linux cooked capture encapsulation v2
|
||||||
sll_packet Linux cooked capture encapsulation
|
sll_packet Linux cooked capture encapsulation
|
||||||
|
@ -50,6 +50,7 @@ import (
|
|||||||
_ "github.com/wader/fq/format/postgres"
|
_ "github.com/wader/fq/format/postgres"
|
||||||
_ "github.com/wader/fq/format/prores"
|
_ "github.com/wader/fq/format/prores"
|
||||||
_ "github.com/wader/fq/format/protobuf"
|
_ "github.com/wader/fq/format/protobuf"
|
||||||
|
_ "github.com/wader/fq/format/pyrdp"
|
||||||
_ "github.com/wader/fq/format/riff"
|
_ "github.com/wader/fq/format/riff"
|
||||||
_ "github.com/wader/fq/format/rtmp"
|
_ "github.com/wader/fq/format/rtmp"
|
||||||
_ "github.com/wader/fq/format/tar"
|
_ "github.com/wader/fq/format/tar"
|
||||||
|
@ -162,6 +162,7 @@ var (
|
|||||||
Protobuf = &decode.Group{Name: "protobuf"}
|
Protobuf = &decode.Group{Name: "protobuf"}
|
||||||
ProtobufWidevine = &decode.Group{Name: "protobuf_widevine"}
|
ProtobufWidevine = &decode.Group{Name: "protobuf_widevine"}
|
||||||
PSSH_Playready = &decode.Group{Name: "pssh_playready"}
|
PSSH_Playready = &decode.Group{Name: "pssh_playready"}
|
||||||
|
PYRDP = &decode.Group{Name: "pyrdp"}
|
||||||
RTMP = &decode.Group{Name: "rtmp"}
|
RTMP = &decode.Group{Name: "rtmp"}
|
||||||
SLL_Packet = &decode.Group{Name: "sll_packet"}
|
SLL_Packet = &decode.Group{Name: "sll_packet"}
|
||||||
SLL2_Packet = &decode.Group{Name: "sll2_packet"}
|
SLL2_Packet = &decode.Group{Name: "sll2_packet"}
|
||||||
|
@ -57,8 +57,12 @@ def _markdown_children_to_text($width):
|
|||||||
| join("")
|
| join("")
|
||||||
) as $text
|
) as $text
|
||||||
| if $text == .destination then $text
|
| if $text == .destination then $text
|
||||||
|
else
|
||||||
|
if .destination | startswith("mailto:") then
|
||||||
|
"<\(.destination[7:])>"
|
||||||
else "\($text) (\(.destination))"
|
else "\($text) (\(.destination))"
|
||||||
end
|
end
|
||||||
|
end
|
||||||
)
|
)
|
||||||
elif .type == "code_block" then .literal | rtrimstr("\n") | split("\n") | " " + join("\n ")
|
elif .type == "code_block" then .literal | rtrimstr("\n") | split("\n") | " " + join("\n ")
|
||||||
elif .type == "code" then .literal
|
elif .type == "code" then .literal
|
||||||
|
109
format/pyrdp/pdu/client_data.go
Normal file
109
format/pyrdp/pdu/client_data.go
Normal file
@ -0,0 +1,109 @@
|
|||||||
|
// Copyright (c) 2022-2023 GoSecure Inc.
|
||||||
|
// Copyright (c) 2024 Flare Systems
|
||||||
|
// Licensed under the MIT License
|
||||||
|
package pdu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/wader/fq/pkg/decode"
|
||||||
|
"github.com/wader/fq/pkg/scalar"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
RDP4 = 0x80001
|
||||||
|
RDP5 = 0x80004
|
||||||
|
RDP10 = 0x80005
|
||||||
|
RDP10_1 = 0x80006
|
||||||
|
RDP10_2 = 0x80007
|
||||||
|
RDP10_3 = 0x80008
|
||||||
|
RDP10_4 = 0x80009
|
||||||
|
RDP10_5 = 0x8000a
|
||||||
|
RDP10_6 = 0x8000b
|
||||||
|
RDP10_7 = 0x8000c
|
||||||
|
RDP10_8 = 0x8000d
|
||||||
|
RDP10_9 = 0x8000e
|
||||||
|
RDP10_10 = 0x8000f
|
||||||
|
)
|
||||||
|
|
||||||
|
var RDPVersionMap = scalar.UintMapSymStr{
|
||||||
|
RDP4: "4",
|
||||||
|
RDP5: "5",
|
||||||
|
RDP10: "10",
|
||||||
|
RDP10_1: "10_1",
|
||||||
|
RDP10_2: "10_2",
|
||||||
|
RDP10_3: "10_3",
|
||||||
|
RDP10_4: "10_4",
|
||||||
|
RDP10_5: "10_5",
|
||||||
|
RDP10_6: "10_6",
|
||||||
|
RDP10_7: "10_7",
|
||||||
|
RDP10_8: "10_8",
|
||||||
|
RDP10_9: "10_9",
|
||||||
|
RDP10_10: "10_10",
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
CLIENT_CORE = 0xc001
|
||||||
|
CLIENT_SECURITY = 0xc002
|
||||||
|
CLIENT_NETWORK = 0xc003
|
||||||
|
CLIENT_CLUSTER = 0xc004
|
||||||
|
)
|
||||||
|
|
||||||
|
var clientDataMap = scalar.UintMapSymStr{
|
||||||
|
CLIENT_CORE: "core",
|
||||||
|
CLIENT_SECURITY: "security",
|
||||||
|
CLIENT_NETWORK: "network",
|
||||||
|
CLIENT_CLUSTER: "cluster",
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseClientData(d *decode.D, length int64) {
|
||||||
|
d.FieldStruct("client_data", func(d *decode.D) {
|
||||||
|
header := d.FieldU16("header", clientDataMap)
|
||||||
|
dataLen := int64(d.FieldU16("length") - 4)
|
||||||
|
|
||||||
|
switch header {
|
||||||
|
case CLIENT_CORE:
|
||||||
|
ParseClientDataCore(d, dataLen)
|
||||||
|
case CLIENT_SECURITY:
|
||||||
|
ParseClientDataSecurity(d, dataLen)
|
||||||
|
case CLIENT_NETWORK:
|
||||||
|
ParseClientDataNetwork(d, dataLen)
|
||||||
|
case CLIENT_CLUSTER:
|
||||||
|
ParseClientDataCluster(d, dataLen)
|
||||||
|
default:
|
||||||
|
// Assert() once all functions are implemented and tested.
|
||||||
|
d.FieldRawLen("data", dataLen*8)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseClientDataCore(d *decode.D, length int64) {
|
||||||
|
d.FieldU32("version", RDPVersionMap)
|
||||||
|
d.FieldU16("desktop_width")
|
||||||
|
d.FieldU16("desktop_height")
|
||||||
|
d.FieldU16("color_depth")
|
||||||
|
d.FieldU16("sas_sequence")
|
||||||
|
d.FieldU32("keyboard_layout")
|
||||||
|
d.FieldU32("client_build")
|
||||||
|
d.FieldUTF16LE("client_name", 32, scalar.StrActualTrim("\x00"))
|
||||||
|
d.FieldU32("keyboard_type")
|
||||||
|
d.FieldU32("keyboard_sub_type")
|
||||||
|
d.FieldU32("keyboard_function_key")
|
||||||
|
d.FieldRawLen("ime_file_name", 64*8)
|
||||||
|
d.FieldRawLen("code_data", 98*8)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseClientDataSecurity(d *decode.D, length int64) {
|
||||||
|
d.FieldU32("encryption_methods")
|
||||||
|
d.FieldU32("ext_encryption_methods")
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseClientDataNetwork(d *decode.D, length int64) {
|
||||||
|
d.FieldU32("channel_count")
|
||||||
|
length -= 4
|
||||||
|
d.FieldRawLen("channel_def_array", length*8)
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseClientDataCluster(d *decode.D, length int64) {
|
||||||
|
d.FieldU32("flags")
|
||||||
|
d.FieldU32("redirected_session_id")
|
||||||
|
}
|
117
format/pyrdp/pdu/client_info.go
Normal file
117
format/pyrdp/pdu/client_info.go
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
// Copyright (c) 2022-2023 GoSecure Inc.
|
||||||
|
// Copyright (c) 2024 Flare Systems
|
||||||
|
// Licensed under the MIT License
|
||||||
|
package pdu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/wader/fq/pkg/decode"
|
||||||
|
"github.com/wader/fq/pkg/scalar"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ParseClientInfo(d *decode.D, length int64) {
|
||||||
|
d.FieldStruct("client_info", func(d *decode.D) {
|
||||||
|
pos := d.Pos()
|
||||||
|
var (
|
||||||
|
isUnicode bool
|
||||||
|
hasNull bool
|
||||||
|
nullN uint64 = 0
|
||||||
|
unicodeN uint64 = 0
|
||||||
|
)
|
||||||
|
codePage := d.FieldU32("code_page")
|
||||||
|
flags := d.U32()
|
||||||
|
d.SeekRel(-4 * 8)
|
||||||
|
d.FieldStruct("flags", decodeFlagsFn)
|
||||||
|
|
||||||
|
isUnicode = ((flags & INFO_UNICODE) != 0)
|
||||||
|
hasNull = (codePage == 1252 || isUnicode)
|
||||||
|
|
||||||
|
if hasNull {
|
||||||
|
nullN = 1
|
||||||
|
}
|
||||||
|
if isUnicode {
|
||||||
|
unicodeN = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
domainLength := int(d.FieldU16("domain_length") + nullN*unicodeN)
|
||||||
|
usernameLength := int(d.FieldU16("username_length") + nullN*unicodeN)
|
||||||
|
passwordLength := int(d.FieldU16("password_length") + nullN*unicodeN)
|
||||||
|
alternateShellLength := int(d.FieldU16("alternate_shell_length") + nullN*unicodeN)
|
||||||
|
workingDirLength := int(d.FieldU16("working_dir_length") + nullN*unicodeN)
|
||||||
|
|
||||||
|
d.FieldUTF16LE("domain", domainLength, scalar.StrActualTrim("\x00"))
|
||||||
|
d.FieldUTF16LE("username", usernameLength, scalar.StrActualTrim("\x00"))
|
||||||
|
d.FieldUTF16LE("password", passwordLength, scalar.StrActualTrim("\x00"))
|
||||||
|
d.FieldUTF16LE("alternate_shell", alternateShellLength, scalar.StrActualTrim("\x00"))
|
||||||
|
d.FieldUTF16LE("working_dir", workingDirLength, scalar.StrActualTrim("\x00"))
|
||||||
|
|
||||||
|
extraLength := length - ((d.Pos() - pos) / 8)
|
||||||
|
if extraLength > 0 {
|
||||||
|
d.FieldStruct("extra_info", func(d *decode.D) {
|
||||||
|
d.FieldU16("address_family", scalar.UintHex)
|
||||||
|
addressLength := int(d.FieldU16("address_length"))
|
||||||
|
d.FieldUTF16LE("address", addressLength, scalar.StrActualTrim("\x00"))
|
||||||
|
clientDirLength := int(d.FieldU16("client_dir_length"))
|
||||||
|
d.FieldUTF16LE("client_dir", clientDirLength, scalar.StrActualTrim("\x00"))
|
||||||
|
// TS_TIME_ZONE_INFORMATION structure
|
||||||
|
// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/526ed635-d7a9-4d3c-bbe1-4e3fb17585f4
|
||||||
|
d.FieldU32("timezone_bias")
|
||||||
|
d.FieldUTF16LE("timezone_standardname", 64, scalar.StrActualTrim("\x00"))
|
||||||
|
})
|
||||||
|
|
||||||
|
// XXX: there's more extra info but here's everything we need from the
|
||||||
|
// client (other than UTC info)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// flags
|
||||||
|
INFO_MOUSE = 0x00000001
|
||||||
|
INFO_DISABLECTRLALTDEL = 0x00000002
|
||||||
|
INFO_AUTOLOGON = 0x00000008
|
||||||
|
INFO_UNICODE = 0x00000010
|
||||||
|
INFO_MAXIMIZESHELL = 0x00000020
|
||||||
|
INFO_LOGONNOTIFY = 0x00000040
|
||||||
|
INFO_COMPRESSION = 0x00000080
|
||||||
|
INFO_ENABLEWINDOWSKEY = 0x00000100
|
||||||
|
INFO_REMOTECONSOLEAUDIO = 0x00002000
|
||||||
|
INFO_FORCE_ENCRYPTED_CS_PDU = 0x00004000
|
||||||
|
INFO_RAIL = 0x00008000
|
||||||
|
INFO_LOGONERRORS = 0x00010000
|
||||||
|
INFO_MOUSE_HAS_WHEEL = 0x00020000
|
||||||
|
INFO_PASSWORD_IS_SC_PIN = 0x00040000
|
||||||
|
INFO_NOAUDIOPLAYBACK = 0x00080000
|
||||||
|
INFO_USING_SAVED_CREDS = 0x00100000
|
||||||
|
INFO_AUDIOCAPTURE = 0x00200000
|
||||||
|
INFO_VIDEO_DISABLE = 0x00400000
|
||||||
|
INFO_RESERVED1 = 0x00800000
|
||||||
|
INFO_RESERVED2 = 0x01000000
|
||||||
|
INFO_HIDEF_RAIL_SUPPORTED = 0x02000000
|
||||||
|
)
|
||||||
|
|
||||||
|
func decodeFlagsFn(d *decode.D) {
|
||||||
|
d.FieldBool("mouse")
|
||||||
|
d.FieldBool("disabledctrlaltdel")
|
||||||
|
d.FieldRawLen("unused0", 1)
|
||||||
|
d.FieldBool("autologon")
|
||||||
|
d.FieldBool("unicode")
|
||||||
|
d.FieldBool("maximizeshell")
|
||||||
|
d.FieldBool("logonnotify")
|
||||||
|
d.FieldBool("compression")
|
||||||
|
d.FieldBool("enablewindowskey")
|
||||||
|
d.FieldRawLen("unused1", 4)
|
||||||
|
d.FieldBool("remoteconsoleaudio")
|
||||||
|
d.FieldBool("force_encrypted_cs_pdu")
|
||||||
|
d.FieldBool("rail")
|
||||||
|
d.FieldBool("logonerrors")
|
||||||
|
d.FieldBool("mouse_has_wheel")
|
||||||
|
d.FieldBool("password_is_sc_pin")
|
||||||
|
d.FieldBool("noaudioplayback")
|
||||||
|
d.FieldBool("using_saved_creds")
|
||||||
|
d.FieldBool("audiocapture")
|
||||||
|
d.FieldBool("video_disable")
|
||||||
|
d.FieldBool("reserved1")
|
||||||
|
d.FieldBool("reserved2")
|
||||||
|
d.FieldBool("hidef_rail_supported")
|
||||||
|
d.FieldRawLen("unused2", 6)
|
||||||
|
}
|
78
format/pyrdp/pdu/clipboard_data.go
Normal file
78
format/pyrdp/pdu/clipboard_data.go
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
// Copyright (c) 2022-2023 GoSecure Inc.
|
||||||
|
// Copyright (c) 2024 Flare Systems
|
||||||
|
// Licensed under the MIT License
|
||||||
|
package pdu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/wader/fq/pkg/decode"
|
||||||
|
"github.com/wader/fq/pkg/scalar"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Message types.
|
||||||
|
CB_MONITOR_READY = 0x0001
|
||||||
|
CB_FORMAT_LIST = 0x0002
|
||||||
|
CB_FORMAT_LIST_RESPONSE = 0x0003
|
||||||
|
CB_FORMAT_DATA_REQUEST = 0x0004
|
||||||
|
CB_FORMAT_DATA_RESPONSE = 0x0005
|
||||||
|
CB_TEMP_DIRECTORY = 0x0006
|
||||||
|
CB_CLIP_CAPS = 0x0007
|
||||||
|
CB_FILECONTENTS_REQUEST = 0x0008
|
||||||
|
CB_FILECONTENTS_RESPONSE = 0x0009
|
||||||
|
CB_LOCK_CLIPDATA = 0x000A
|
||||||
|
CB_UNLOCK_CLIPDATA = 0x000B
|
||||||
|
|
||||||
|
// Message flags.
|
||||||
|
NONE = 0
|
||||||
|
CB_RESPONSE_OK = 0x0001
|
||||||
|
CB_RESPONSE_FAIL = 0x0002
|
||||||
|
CB_ASCII_NAMES = 0x0004
|
||||||
|
)
|
||||||
|
|
||||||
|
var cbTypesMap = scalar.UintMapSymStr{
|
||||||
|
CB_MONITOR_READY: "monitor_ready",
|
||||||
|
CB_FORMAT_LIST: "format_list",
|
||||||
|
CB_FORMAT_LIST_RESPONSE: "format_list_response",
|
||||||
|
CB_FORMAT_DATA_REQUEST: "format_data_request",
|
||||||
|
CB_FORMAT_DATA_RESPONSE: "format_data_response",
|
||||||
|
CB_TEMP_DIRECTORY: "temp_directory",
|
||||||
|
CB_CLIP_CAPS: "clip_caps",
|
||||||
|
CB_FILECONTENTS_REQUEST: "filecontents_request",
|
||||||
|
CB_FILECONTENTS_RESPONSE: "filecontents_response",
|
||||||
|
CB_LOCK_CLIPDATA: "lock_clipdata",
|
||||||
|
CB_UNLOCK_CLIPDATA: "unlock_clipdata",
|
||||||
|
}
|
||||||
|
|
||||||
|
var cbFlagsMap = scalar.UintMapSymStr{
|
||||||
|
NONE: "none",
|
||||||
|
CB_RESPONSE_OK: "response_ok",
|
||||||
|
CB_RESPONSE_FAIL: "response_fail",
|
||||||
|
CB_ASCII_NAMES: "ascii_names",
|
||||||
|
}
|
||||||
|
|
||||||
|
var cbParseFnMap = map[uint16]interface{}{
|
||||||
|
CB_FORMAT_DATA_RESPONSE: parseCbFormatDataResponse,
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseClipboardData(d *decode.D, length int64) {
|
||||||
|
d.FieldStruct("clipboard_data", func(d *decode.D) {
|
||||||
|
msgType := uint16(d.FieldU16("msg_type", cbTypesMap))
|
||||||
|
d.FieldU16("msg_flags", cbFlagsMap)
|
||||||
|
dataLength := d.FieldU32("data_len")
|
||||||
|
|
||||||
|
cbParser, ok := cbParseFnMap[msgType]
|
||||||
|
if ok {
|
||||||
|
parseFn, ok := cbParser.(func(d *decode.D, length uint64))
|
||||||
|
if ok {
|
||||||
|
parseFn(d, dataLength)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Assert() once all functions are implemented.
|
||||||
|
d.FieldRawLen("data", int64(dataLength*8))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseCbFormatDataResponse(d *decode.D, length uint64) {
|
||||||
|
d.FieldRawLen("data", int64(length*8))
|
||||||
|
}
|
129
format/pyrdp/pdu/fastpath_input.go
Normal file
129
format/pyrdp/pdu/fastpath_input.go
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
// Copyright (c) 2022-2023 GoSecure Inc.
|
||||||
|
// Copyright (c) 2024 Flare Systems
|
||||||
|
// Licensed under the MIT License
|
||||||
|
package pdu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/wader/fq/pkg/decode"
|
||||||
|
"github.com/wader/fq/pkg/scalar"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// Security Flags.
|
||||||
|
FASTPATH_INPUT_SECURE_CHECKSUM = 1
|
||||||
|
FASTPATH_INPUT_ENCRYPTED = 2
|
||||||
|
|
||||||
|
// Event codes.
|
||||||
|
FASTPATH_INPUT_EVENT_SCANCODE = 0
|
||||||
|
FASTPATH_INPUT_EVENT_MOUSE = 1
|
||||||
|
FASTPATH_INPUT_EVENT_MOUSEX = 2
|
||||||
|
FASTPATH_INPUT_EVENT_SYNC = 3
|
||||||
|
FASTPATH_INPUT_EVENT_UNICODE = 4
|
||||||
|
FASTPATH_INPUT_EVENT_QOE_TIMESTAMP = 6
|
||||||
|
)
|
||||||
|
|
||||||
|
// commented because unused but we should use one-day
|
||||||
|
//var eventCodesMap = scalar.UintMapSymStr{
|
||||||
|
// FASTPATH_INPUT_EVENT_SCANCODE: "fastpath_input_event_scancode",
|
||||||
|
// FASTPATH_INPUT_EVENT_MOUSE: "fastpath_input_event_mouse",
|
||||||
|
// FASTPATH_INPUT_EVENT_MOUSEX: "fastpath_input_event_mousex",
|
||||||
|
// FASTPATH_INPUT_EVENT_SYNC: "fastpath_input_event_sync",
|
||||||
|
// FASTPATH_INPUT_EVENT_UNICODE: "fastpath_input_event_unicode",
|
||||||
|
// FASTPATH_INPUT_EVENT_QOE_TIMESTAMP: "fastpath_input_event_qoe_timestamp",
|
||||||
|
//}
|
||||||
|
|
||||||
|
//var eventFnMap = map[int]interface{}{
|
||||||
|
// FASTPATH_INPUT_EVENT_SCANCODE: parseFastpathInputEventScancode,
|
||||||
|
// FASTPATH_INPUT_EVENT_MOUSE: parseFastpathInputEventMouse,
|
||||||
|
// FASTPATH_INPUT_EVENT_MOUSEX: parseFastpathInputEventMousex,
|
||||||
|
// FASTPATH_INPUT_EVENT_SYNC: parseFastpathInputEventSync,
|
||||||
|
// FASTPATH_INPUT_EVENT_UNICODE: parseFastpathInputEventUnicode,
|
||||||
|
// FASTPATH_INPUT_EVENT_QOE_TIMESTAMP: parseFastpathInputEventQoeTimestamp,
|
||||||
|
//}
|
||||||
|
|
||||||
|
//var fastPathInputEventLengthsMap = map[int]int{
|
||||||
|
// FASTPATH_INPUT_EVENT_SCANCODE: 2,
|
||||||
|
// FASTPATH_INPUT_EVENT_MOUSE: 7,
|
||||||
|
// FASTPATH_INPUT_EVENT_MOUSEX: 7,
|
||||||
|
// FASTPATH_INPUT_EVENT_SYNC: 1,
|
||||||
|
// FASTPATH_INPUT_EVENT_UNICODE: 3,
|
||||||
|
// FASTPATH_INPUT_EVENT_QOE_TIMESTAMP: 5,
|
||||||
|
//}
|
||||||
|
|
||||||
|
func ParseFastPathInput(d *decode.D, length int64) {
|
||||||
|
d.FieldStruct("fastpath_input", func(d *decode.D) {
|
||||||
|
// var (
|
||||||
|
// events uint8 = 1
|
||||||
|
// )
|
||||||
|
pos := d.Pos()
|
||||||
|
|
||||||
|
d.FieldStruct("input_header", func(d *decode.D) {
|
||||||
|
d.FieldU2("action", scalar.UintHex)
|
||||||
|
// events = uint8(d.FieldU4("events") & 0xf)
|
||||||
|
d.FieldU4("events", scalar.UintHex)
|
||||||
|
flags := d.FieldU2("flags", scalar.UintHex)
|
||||||
|
if flags&FASTPATH_INPUT_ENCRYPTED != 0 {
|
||||||
|
panic("Encrypted fast-path not implemented.")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
inputLength := d.FieldU8("input_length1", scalar.UintHex)
|
||||||
|
if inputLength&0x80 != 0 {
|
||||||
|
inputLength = ((inputLength & 0x7f) << 8) | d.FieldU8("input_length2", scalar.UintHex)
|
||||||
|
}
|
||||||
|
|
||||||
|
// d.FieldU64("data_signature", scalar.Hex)
|
||||||
|
// fmt.Fprintf(os.Stderr, "events:%d\n", events)
|
||||||
|
// d.FieldArray("events", func(d *decode.D) {
|
||||||
|
// for ; events > 0; events-- {
|
||||||
|
// var event_type int
|
||||||
|
//
|
||||||
|
// d.FieldStruct("event_header", func(d *decode.D) {
|
||||||
|
// event_type = int(d.FieldU3("type", eventCodesMap))
|
||||||
|
// d.FieldU5("flags")
|
||||||
|
// })
|
||||||
|
//
|
||||||
|
// if _, ok := eventFnMap[event_type]; !ok {
|
||||||
|
// // panic("fastpath_input: Unknow event code.\n")
|
||||||
|
// fmt.Fprint(os.Stderr, "fastpath_input: Unknow event code.\n")
|
||||||
|
// } else {
|
||||||
|
// eventFnMap[event_type].(func(d *decode.D))(d)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
|
||||||
|
inputLength -= uint64(d.Pos()-pos) / 8
|
||||||
|
if inputLength > 0 {
|
||||||
|
d.FieldRawLen("data", int64(inputLength*8))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//commented because unused but we should use one-day
|
||||||
|
//func parseFastpathInputEventScancode(d *decode.D) {
|
||||||
|
// // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/089d362b-31eb-4a1a-b6fa-92fe61bb5dbf
|
||||||
|
// d.FieldU8("key_code", CharMapper)
|
||||||
|
//}
|
||||||
|
|
||||||
|
//func parseFastpathInputEventMouse(d *decode.D) {
|
||||||
|
// // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/16a96ded-b3d3-4468-b993-9c7a51297510
|
||||||
|
// d.FieldU16("pointer_flags", scalar.UintHex)
|
||||||
|
// d.FieldU16("x")
|
||||||
|
// d.FieldU16("y")
|
||||||
|
//}
|
||||||
|
//func parseFastpathInputEventMousex(d *decode.D) {
|
||||||
|
// // https: //docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/2ef7632f-2f2a-4de7-ab58-2585cedcdf48
|
||||||
|
// d.FieldU16("pointer_flags", scalar.UintHex)
|
||||||
|
// d.FieldU16("x")
|
||||||
|
// d.FieldU16("y")
|
||||||
|
//}
|
||||||
|
//func parseFastpathInputEventSync(d *decode.D) {
|
||||||
|
// // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/6c5d0ef9-4653-4d69-9ba9-09ba3acd660f
|
||||||
|
// d.FieldU16("padding")
|
||||||
|
// d.FieldU32("toggle_flags")
|
||||||
|
//}
|
||||||
|
//func parseFastpathInputEventUnicode(d *decode.D) {
|
||||||
|
// // https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/e7b13e98-d800-42bb-9a1d-6948537d2317
|
||||||
|
// d.FieldU16("unicode_code", scalar.UintHex)
|
||||||
|
//}
|
||||||
|
//func parseFastpathInputEventQoeTimestamp(d *decode.D) {}
|
16
format/pyrdp/pdu/util.go
Normal file
16
format/pyrdp/pdu/util.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
// Copyright (c) 2022-2023 GoSecure Inc.
|
||||||
|
// Copyright (c) 2024 Flare Systems
|
||||||
|
// Licensed under the MIT License
|
||||||
|
package pdu
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/wader/fq/pkg/scalar"
|
||||||
|
)
|
||||||
|
|
||||||
|
var CharMapper = scalar.UintFn(func(s scalar.Uint) (scalar.Uint, error) {
|
||||||
|
char := s.Actual
|
||||||
|
s.Sym = fmt.Sprintf("%c", int(char))
|
||||||
|
return s, nil
|
||||||
|
})
|
146
format/pyrdp/pyrdp.go
Normal file
146
format/pyrdp/pyrdp.go
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
// Processes PyRDP replay files
|
||||||
|
// https://github.com/GoSecure/pyrdp
|
||||||
|
//
|
||||||
|
// Copyright (c) 2022-2023 GoSecure Inc.
|
||||||
|
// Copyright (c) 2024 Flare Systems
|
||||||
|
// Licensed under the MIT License
|
||||||
|
//
|
||||||
|
// Maintainer: Olivier Bilodeau <olivier.bilodeau@flare.io>
|
||||||
|
// Author: Lisandro Ubiedo
|
||||||
|
package pyrdp
|
||||||
|
|
||||||
|
import (
|
||||||
|
"embed"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/wader/fq/format"
|
||||||
|
pyrdp_pdu "github.com/wader/fq/format/pyrdp/pdu"
|
||||||
|
"github.com/wader/fq/pkg/decode"
|
||||||
|
"github.com/wader/fq/pkg/interp"
|
||||||
|
"github.com/wader/fq/pkg/scalar"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:embed pyrdp.md
|
||||||
|
var pyrdpFS embed.FS
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
interp.RegisterFormat(
|
||||||
|
format.PYRDP,
|
||||||
|
&decode.Format{
|
||||||
|
Description: "PyRDP Replay Files",
|
||||||
|
DecodeFn: decodePYRDP,
|
||||||
|
})
|
||||||
|
interp.RegisterFS(pyrdpFS)
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
READ_EXTRA = true
|
||||||
|
|
||||||
|
// PDU Types.
|
||||||
|
PDU_FAST_PATH_INPUT = 1 // Ex: scan codes, mouse, etc.
|
||||||
|
PDU_FAST_PATH_OUTPUT = 2 // Ex: image
|
||||||
|
PDU_CLIENT_INFO = 3 // Creds on connection
|
||||||
|
PDU_SLOW_PATH_PDU = 4 // For slow-path PDUs
|
||||||
|
PDU_CONNECTION_CLOSE = 5 // To advertise the end of the connection
|
||||||
|
PDU_CLIPBOARD_DATA = 6 // To collect clipboard data
|
||||||
|
PDU_CLIENT_DATA = 7 // Contains the clientName
|
||||||
|
PDU_MOUSE_MOVE = 8 // Mouse move event from the player
|
||||||
|
PDU_MOUSE_BUTTON = 9 // Mouse button event from the player
|
||||||
|
PDU_MOUSE_WHEEL = 10 // Mouse wheel event from the player
|
||||||
|
PDU_KEYBOARD = 11 // Keyboard event from the player
|
||||||
|
PDU_TEXT = 12 // Text event from the player
|
||||||
|
PDU_FORWARDING_STATE = 13 // Event from the player to change the state of I/O forwarding
|
||||||
|
PDU_BITMAP = 14 // Bitmap event from the player
|
||||||
|
PDU_DEVICE_MAPPING = 15 // Device mapping event notification
|
||||||
|
PDU_DIRECTORY_LISTING_REQUEST = 16 // Directory listing request from the player
|
||||||
|
PDU_DIRECTORY_LISTING_RESPONSE = 17 // Directory listing response to the player
|
||||||
|
PDU_FILE_DOWNLOAD_REQUEST = 18 // File download request from the player
|
||||||
|
PDU_FILE_DOWNLOAD_RESPONSE = 19 // File download response to the player
|
||||||
|
PDU_FILE_DOWNLOAD_COMPLETE = 20 // File download completion notification to the player
|
||||||
|
)
|
||||||
|
|
||||||
|
var pduTypesMap = scalar.UintMapSymStr{
|
||||||
|
PDU_FAST_PATH_INPUT: "fastpath_input",
|
||||||
|
PDU_FAST_PATH_OUTPUT: "fastpath_output",
|
||||||
|
PDU_CLIENT_INFO: "client_info",
|
||||||
|
PDU_SLOW_PATH_PDU: "slow_path_pdu",
|
||||||
|
PDU_CONNECTION_CLOSE: "connection_close",
|
||||||
|
PDU_CLIPBOARD_DATA: "clipboard_data",
|
||||||
|
PDU_CLIENT_DATA: "client_data",
|
||||||
|
PDU_MOUSE_MOVE: "mouse_move",
|
||||||
|
PDU_MOUSE_BUTTON: "mouse_button",
|
||||||
|
PDU_MOUSE_WHEEL: "mouse_wheel",
|
||||||
|
PDU_KEYBOARD: "keyboard",
|
||||||
|
PDU_TEXT: "text",
|
||||||
|
PDU_FORWARDING_STATE: "forwarding_state",
|
||||||
|
PDU_BITMAP: "bitmap",
|
||||||
|
PDU_DEVICE_MAPPING: "device_mapping",
|
||||||
|
PDU_DIRECTORY_LISTING_REQUEST: "directory_listing_request",
|
||||||
|
PDU_DIRECTORY_LISTING_RESPONSE: "directory_listing_response",
|
||||||
|
PDU_FILE_DOWNLOAD_REQUEST: "file_download_request",
|
||||||
|
PDU_FILE_DOWNLOAD_RESPONSE: "file_download_response",
|
||||||
|
PDU_FILE_DOWNLOAD_COMPLETE: "file_download_complete",
|
||||||
|
}
|
||||||
|
|
||||||
|
var pduParsersMap = map[uint16]interface{}{
|
||||||
|
PDU_FAST_PATH_INPUT: pyrdp_pdu.ParseFastPathInput,
|
||||||
|
// PDU_FAST_PATH_OUTPUT: pyrdp_pdu.ParseFastPathOut,
|
||||||
|
PDU_CLIENT_INFO: pyrdp_pdu.ParseClientInfo,
|
||||||
|
// PDU_SLOW_PATH_PDU: pyrdp_pdu.ParseSlowPathPDU,
|
||||||
|
PDU_CONNECTION_CLOSE: noParse,
|
||||||
|
PDU_CLIPBOARD_DATA: pyrdp_pdu.ParseClipboardData,
|
||||||
|
PDU_CLIENT_DATA: pyrdp_pdu.ParseClientData,
|
||||||
|
// PDU_MOUSE_MOVE: pyrdp_pdu.ParseMouseMove,
|
||||||
|
// PDU_MOUSE_BUTTON: pyrdp_pdu.ParseMouseButton,
|
||||||
|
// PDU_MOUSE_WHEEL: pyrdp_pdu.ParseMouseWheel,
|
||||||
|
// PDU_KEYBOARD: pyrdp_pdu.ParseKeyboard,
|
||||||
|
// PDU_TEXT: pyrdp_pdu.ParseText,
|
||||||
|
// PDU_FORWARDING_STATE: pyrdp_pdu.ParseForwardingState,
|
||||||
|
// PDU_BITMAP: pyrdp_pdu.ParseBitmap,
|
||||||
|
// PDU_DEVICE_MAPPING: pyrdp_pdu.ParseDeviceMapping,
|
||||||
|
// PDU_DIRECTORY_LISTING_REQUEST: pyrdp_pdu.ParseDirectoryListingRequest,
|
||||||
|
// PDU_DIRECTORY_LISTING_RESPONSE: pyrdp_pdu.ParseDirectoryListingResponse,
|
||||||
|
// PDU_FILE_DOWNLOAD_REQUEST: pyrdp_pdu.ParseFileDownloadRequest,
|
||||||
|
// PDU_FILE_DOWNLOAD_RESPONSE: pyrdp_pdu.ParseFileDownloadResponse,
|
||||||
|
// PDU_FILE_DOWNLOAD_COMPLETE: pyrdp_pdu.ParseFileDownloadComplete,
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodePYRDP(d *decode.D) any {
|
||||||
|
d.Endian = decode.LittleEndian
|
||||||
|
|
||||||
|
d.FieldArray("events", func(d *decode.D) {
|
||||||
|
for !d.End() {
|
||||||
|
d.FieldStruct("event", func(d *decode.D) {
|
||||||
|
pos := d.Pos()
|
||||||
|
|
||||||
|
size := d.FieldU64("size") // minus the length
|
||||||
|
pduType := uint16(d.FieldU16("pdu_type", pduTypesMap))
|
||||||
|
d.FieldU64("timestamp", scalar.UintActualUnixTimeDescription(time.Millisecond, time.RFC3339Nano))
|
||||||
|
pduSize := int64(size - 18)
|
||||||
|
|
||||||
|
pduParser, ok := pduParsersMap[pduType]
|
||||||
|
if !ok { // catch undeclared parsers
|
||||||
|
if pduSize > 0 {
|
||||||
|
d.FieldRawLen("data", pduSize*8)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
parseFn, ok := pduParser.(func(d *decode.D, length int64))
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
parseFn(d, pduSize)
|
||||||
|
|
||||||
|
curr := d.Pos() - pos
|
||||||
|
if READ_EXTRA {
|
||||||
|
d.FieldRawLen("extra", (int64(size)*8)-curr) // seek whatever is left
|
||||||
|
} else {
|
||||||
|
d.SeekRel((int64(size) * 8) - curr) // read whatever is left
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func noParse(d *decode.D, length int64) {}
|
6
format/pyrdp/pyrdp.md
Normal file
6
format/pyrdp/pyrdp.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
### Authors
|
||||||
|
- Olivier Bilodeau <olivier.bilodeau@flare.io>, Maintainer
|
||||||
|
- Lisandro Ubiedo, Author
|
||||||
|
|
||||||
|
### References
|
||||||
|
- https://github.com/GoSecure/pyrdp
|
3569
format/pyrdp/testdata/test.fqtest
vendored
Normal file
3569
format/pyrdp/testdata/test.fqtest
vendored
Normal file
File diff suppressed because it is too large
Load Diff
BIN
format/pyrdp/testdata/test.pyrdp
vendored
Normal file
BIN
format/pyrdp/testdata/test.pyrdp
vendored
Normal file
Binary file not shown.
8
go.mod
8
go.mod
@ -48,7 +48,7 @@ require (
|
|||||||
// bump: gomod-golang-x-crypto /golang\.org\/x\/crypto v(.*)/ https://github.com/golang/crypto.git|^0
|
// bump: gomod-golang-x-crypto /golang\.org\/x\/crypto v(.*)/ https://github.com/golang/crypto.git|^0
|
||||||
// bump: gomod-golang-x-crypto command go get -d golang.org/x/crypto@v$LATEST && go mod tidy
|
// bump: gomod-golang-x-crypto command go get -d golang.org/x/crypto@v$LATEST && go mod tidy
|
||||||
// bump: gomod-golang-x-crypto link "Tags" https://github.com/golang/crypto/tags
|
// bump: gomod-golang-x-crypto link "Tags" https://github.com/golang/crypto/tags
|
||||||
golang.org/x/crypto v0.23.0
|
golang.org/x/crypto v0.24.0
|
||||||
|
|
||||||
// has no tags
|
// has no tags
|
||||||
// go get -d golang.org/x/exp@master && go mod tidy
|
// go get -d golang.org/x/exp@master && go mod tidy
|
||||||
@ -57,12 +57,12 @@ require (
|
|||||||
// bump: gomod-golang-x-net /golang\.org\/x\/net v(.*)/ https://github.com/golang/net.git|^0
|
// bump: gomod-golang-x-net /golang\.org\/x\/net v(.*)/ https://github.com/golang/net.git|^0
|
||||||
// bump: gomod-golang-x-net command go get -d golang.org/x/net@v$LATEST && go mod tidy
|
// bump: gomod-golang-x-net command go get -d golang.org/x/net@v$LATEST && go mod tidy
|
||||||
// bump: gomod-golang-x-net link "Tags" https://github.com/golang/net/tags
|
// bump: gomod-golang-x-net link "Tags" https://github.com/golang/net/tags
|
||||||
golang.org/x/net v0.25.0
|
golang.org/x/net v0.26.0
|
||||||
|
|
||||||
// bump: gomod-golang-x-term /golang\.org\/x\/term v(.*)/ https://github.com/golang/term.git|^0
|
// bump: gomod-golang-x-term /golang\.org\/x\/term v(.*)/ https://github.com/golang/term.git|^0
|
||||||
// bump: gomod-golang-x-term command go get -d golang.org/x/term@v$LATEST && go mod tidy
|
// bump: gomod-golang-x-term command go get -d golang.org/x/term@v$LATEST && go mod tidy
|
||||||
// bump: gomod-golang-x-term link "Tags" https://github.com/golang/term/tags
|
// bump: gomod-golang-x-term link "Tags" https://github.com/golang/term/tags
|
||||||
golang.org/x/term v0.20.0
|
golang.org/x/term v0.21.0
|
||||||
|
|
||||||
// bump: gomod-golang/text /golang\.org\/x\/text v(.*)/ https://github.com/golang/text.git|^0
|
// bump: gomod-golang/text /golang\.org\/x\/text v(.*)/ https://github.com/golang/text.git|^0
|
||||||
// bump: gomod-golang/text command go get -d golang.org/x/text@v$LATEST && go mod tidy
|
// bump: gomod-golang/text command go get -d golang.org/x/text@v$LATEST && go mod tidy
|
||||||
@ -79,6 +79,6 @@ require (
|
|||||||
github.com/itchyny/timefmt-go v0.1.5 // indirect
|
github.com/itchyny/timefmt-go v0.1.5 // indirect
|
||||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
|
||||||
golang.org/x/sys v0.20.0 // indirect
|
golang.org/x/sys v0.21.0 // indirect
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
|
||||||
)
|
)
|
||||||
|
16
go.sum
16
go.sum
@ -25,16 +25,16 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb
|
|||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/wader/gojq v0.12.1-0.20240401131232-6c6bc364201a h1:P881Oecjt9FEXrwkGJ6UObJksxejJaF/fKq1ZfXpiVE=
|
github.com/wader/gojq v0.12.1-0.20240401131232-6c6bc364201a h1:P881Oecjt9FEXrwkGJ6UObJksxejJaF/fKq1ZfXpiVE=
|
||||||
github.com/wader/gojq v0.12.1-0.20240401131232-6c6bc364201a/go.mod h1:qVrzkUdnBtJvM4twyRQ6xdziPSnSp35dLm4s/DN2iP4=
|
github.com/wader/gojq v0.12.1-0.20240401131232-6c6bc364201a/go.mod h1:qVrzkUdnBtJvM4twyRQ6xdziPSnSp35dLm4s/DN2iP4=
|
||||||
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
|
||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
|
||||||
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw=
|
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8 h1:aAcj0Da7eBAtrTp03QXWvm88pSyOt+UgdZw2BFZ+lEw=
|
||||||
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ=
|
golang.org/x/exp v0.0.0-20240325151524-a685a6edb6d8/go.mod h1:CQ1k9gNrJ50XIzaKCRR2hssIjF07kZFEiieALBM/ARQ=
|
||||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
||||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||||
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
|
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
|
golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA=
|
||||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0=
|
||||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
Loading…
Reference in New Issue
Block a user