1
1
mirror of https://github.com/wader/fq.git synced 2024-09-11 20:07:11 +03:00

Compare commits

..

28 Commits

Author SHA1 Message Date
Mattias Wadman
3f2aa75ec8 pyrdp: Add unused fields to replace gap fields 2024-06-14 23:55:59 +02:00
Mattias Wadman
9874077e20 pyrdp: Less symbol stuttering 2024-06-14 23:55:59 +02:00
Mattias Wadman
3966035eba pyrdp: camelCase vars and lowercase number literals 2024-06-14 23:55:59 +02:00
Mattias Wadman
9db82260e5 pyrdp: Use field description for formatted timestamp
Same as other formats that use timestamps and makes it easier to use them in query,
number instead of a formatted string. Can still use todescription/0 to get
formatted timestamp.
2024-06-14 23:55:59 +02:00
Mattias Wadman
52eaf10de2 help: Render mailto:addr as <addr> 2024-06-14 23:55:59 +02:00
Mattias Wadman
a1fb076248 pyrdp: Add doc and move init func to top 2024-06-14 23:55:59 +02:00
Olivier Bilodeau
6caa7fa78b Resolved all linter errors 2024-06-14 23:55:59 +02:00
Olivier Bilodeau
f5471adb4f doc: added format to README 2024-06-14 23:55:59 +02:00
Olivier Bilodeau
7f42d64e44 removed dead code 2024-06-14 23:55:59 +02:00
Olivier Bilodeau
58f4f61ac5 refactor: package name aligned with directory name 2024-06-14 23:55:59 +02:00
Olivier Bilodeau
5bfe27803b refactoring: UintMap to UintMapSymStr 2024-06-14 23:55:59 +02:00
Olivier Bilodeau
30929cde85 refactor: Changed all FieldStrFn callers to FieldUTF16LE
One fieldname change clientDir to client_dir to align with everything else
2024-06-14 23:55:59 +02:00
Olivier Bilodeau
41988023bc Clarified MIT license usage alongside copyright info 2024-06-14 23:55:59 +02:00
Olivier Bilodeau
f4d9428855 Sending PyRDP parser upstream
For project history see: https://github.com/GoSecure/fq-pyrdp/

Co-authored-by: Lisandro Ubiedo <lubiedo@gosecure.net>
2024-06-14 23:55:59 +02:00
Mattias Wadman
2bc6c768c7
Merge pull request #965 from wader/bump-make-golangci-lint-1.59.1
Update make-golangci-lint to 1.59.1 from 1.59.0
2024-06-10 17:27:28 +01:00
Mattias Wadman
b3e5be095b
Merge pull request #966 from wader/bump-github-golangci-lint-1.59.1
Update github-golangci-lint to 1.59.1 from 1.59.0
2024-06-10 17:27:22 +01:00
bump
6383626aa3 Update github-golangci-lint to 1.59.1 from 1.59.0
Release notes https://github.com/golangci/golangci-lint/releases/tag/v1.59.1
2024-06-10 16:05:37 +00:00
bump
71476743a0 Update make-golangci-lint to 1.59.1 from 1.59.0
Release notes https://github.com/golangci/golangci-lint/releases/tag/v1.59.1
2024-06-10 16:05:35 +00:00
Mattias Wadman
19bd2fbd7c
Merge pull request #962 from wader/bump-gomod-golang-x-net-0.26.0
Update gomod-golang-x-net to 0.26.0 from 0.25.0
2024-06-05 19:33:31 +02:00
bump
c55e10667c Update gomod-golang-x-net to 0.26.0 from 0.25.0
Tags https://github.com/golang/net/tags
2024-06-05 19:24:19 +02:00
Mattias Wadman
292bd02397
Merge pull request #960 from wader/bump-docker-golang-1.22.4
Update docker-golang to 1.22.4 from 1.22.3
2024-06-05 18:55:09 +02:00
Mattias Wadman
bbdd43f5c8
Merge pull request #964 from wader/bump-github-go-version-1.22.4
Update github-go-version to 1.22.4 from 1.22.3
2024-06-05 18:54:26 +02:00
Mattias Wadman
35a8eddf04
Merge pull request #963 from wader/bump-gomod-golang-x-term-0.21.0
Update gomod-golang-x-term to 0.21.0 from 0.20.0
2024-06-05 18:54:09 +02:00
Mattias Wadman
8df50bf62f
Merge pull request #961 from wader/bump-gomod-golang-x-crypto-0.24.0
Update gomod-golang-x-crypto to 0.24.0 from 0.23.0
2024-06-05 18:27:04 +02:00
bump
1ff5a3fadf Update github-go-version to 1.22.4 from 1.22.3 2024-06-05 16:04:19 +00:00
bump
7566fd9307 Update gomod-golang-x-term to 0.21.0 from 0.20.0
Tags https://github.com/golang/term/tags
2024-06-05 16:04:16 +00:00
bump
f7cbf84469 Update gomod-golang-x-crypto to 0.24.0 from 0.23.0
Tags https://github.com/golang/crypto/tags
2024-06-05 16:04:11 +00:00
bump
ab09d3ce6f Update docker-golang to 1.22.4 from 1.22.3 2024-06-05 16:04:06 +00:00
16 changed files with 927 additions and 906 deletions

View File

@ -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 }}

View File

@ -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

View File

@ -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 \

View File

@ -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

View File

@ -138,7 +138,7 @@ prores_frame,
[protobuf](doc/formats.md#protobuf), [protobuf](doc/formats.md#protobuf),
protobuf_widevine, protobuf_widevine,
pssh_playready, pssh_playready,
pyrdp, [pyrdp](doc/formats.md#pyrdp),
[rtmp](doc/formats.md#rtmp), [rtmp](doc/formats.md#rtmp),
sll2_packet, sll2_packet,
sll_packet, sll_packet,

View File

@ -110,6 +110,7 @@
|[`protobuf`](#protobuf) |Protobuf |<sub></sub>| |[`protobuf`](#protobuf) |Protobuf |<sub></sub>|
|`protobuf_widevine` |Widevine&nbsp;protobuf |<sub>`protobuf`</sub>| |`protobuf_widevine` |Widevine&nbsp;protobuf |<sub>`protobuf`</sub>|
|`pssh_playready` |PlayReady&nbsp;PSSH |<sub></sub>| |`pssh_playready` |PlayReady&nbsp;PSSH |<sub></sub>|
|[`pyrdp`](#pyrdp) |PyRDP&nbsp;Replay&nbsp;Files |<sub></sub>|
|[`rtmp`](#rtmp) |Real-Time&nbsp;Messaging&nbsp;Protocol |<sub>`amf0` `mpeg_asc`</sub>| |[`rtmp`](#rtmp) |Real-Time&nbsp;Messaging&nbsp;Protocol |<sub>`amf0` `mpeg_asc`</sub>|
|`sll2_packet` |Linux&nbsp;cooked&nbsp;capture&nbsp;encapsulation&nbsp;v2 |<sub>`inet_packet`</sub>| |`sll2_packet` |Linux&nbsp;cooked&nbsp;capture&nbsp;encapsulation&nbsp;v2 |<sub>`inet_packet`</sub>|
|`sll_packet` |Linux&nbsp;cooked&nbsp;capture&nbsp;encapsulation |<sub>`inet_packet`</sub>| |`sll_packet` |Linux&nbsp;cooked&nbsp;capture&nbsp;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.

View File

@ -57,7 +57,11 @@ def _markdown_children_to_text($width):
| join("") | join("")
) as $text ) as $text
| if $text == .destination then $text | if $text == .destination then $text
else "\($text) (\(.destination))" else
if .destination | startswith("mailto:") then
"<\(.destination[7:])>"
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 ")

View File

@ -16,61 +16,61 @@ const (
RDP10_2 = 0x80007 RDP10_2 = 0x80007
RDP10_3 = 0x80008 RDP10_3 = 0x80008
RDP10_4 = 0x80009 RDP10_4 = 0x80009
RDP10_5 = 0x8000A RDP10_5 = 0x8000a
RDP10_6 = 0x8000B RDP10_6 = 0x8000b
RDP10_7 = 0x8000C RDP10_7 = 0x8000c
RDP10_8 = 0x8000d RDP10_8 = 0x8000d
RDP10_9 = 0x8000e RDP10_9 = 0x8000e
RDP10_10 = 0x8000f RDP10_10 = 0x8000f
) )
var RDPVersionMap = scalar.UintMapSymStr{ var RDPVersionMap = scalar.UintMapSymStr{
RDP4: "rdp4", RDP4: "4",
RDP5: "rdp5", RDP5: "5",
RDP10: "rdp10", RDP10: "10",
RDP10_1: "rdp10_1", RDP10_1: "10_1",
RDP10_2: "rdp10_2", RDP10_2: "10_2",
RDP10_3: "rdp10_3", RDP10_3: "10_3",
RDP10_4: "rdp10_4", RDP10_4: "10_4",
RDP10_5: "rdp10_5", RDP10_5: "10_5",
RDP10_6: "rdp10_6", RDP10_6: "10_6",
RDP10_7: "rdp10_7", RDP10_7: "10_7",
RDP10_8: "rdp10_8", RDP10_8: "10_8",
RDP10_9: "rdp10_9", RDP10_9: "10_9",
RDP10_10: "rdp10_10", RDP10_10: "10_10",
} }
const ( const (
CLIENT_CORE = 0xC001 CLIENT_CORE = 0xc001
CLIENT_SECURITY = 0xC002 CLIENT_SECURITY = 0xc002
CLIENT_NETWORK = 0xC003 CLIENT_NETWORK = 0xc003
CLIENT_CLUSTER = 0xC004 CLIENT_CLUSTER = 0xc004
) )
var clientDataMap = scalar.UintMapSymStr{ var clientDataMap = scalar.UintMapSymStr{
CLIENT_CORE: "client_core", CLIENT_CORE: "core",
CLIENT_SECURITY: "client_security", CLIENT_SECURITY: "security",
CLIENT_NETWORK: "client_network", CLIENT_NETWORK: "network",
CLIENT_CLUSTER: "client_cluster", CLIENT_CLUSTER: "cluster",
} }
func ParseClientData(d *decode.D, length int64) { func ParseClientData(d *decode.D, length int64) {
d.FieldStruct("client_data", func(d *decode.D) { d.FieldStruct("client_data", func(d *decode.D) {
header := d.FieldU16("header", clientDataMap) header := d.FieldU16("header", clientDataMap)
data_len := int64(d.FieldU16("length") - 4) dataLen := int64(d.FieldU16("length") - 4)
switch header { switch header {
case CLIENT_CORE: case CLIENT_CORE:
ParseClientDataCore(d, data_len) ParseClientDataCore(d, dataLen)
case CLIENT_SECURITY: case CLIENT_SECURITY:
ParseClientDataSecurity(d, data_len) ParseClientDataSecurity(d, dataLen)
case CLIENT_NETWORK: case CLIENT_NETWORK:
ParseClientDataNetwork(d, data_len) ParseClientDataNetwork(d, dataLen)
case CLIENT_CLUSTER: case CLIENT_CLUSTER:
ParseClientDataCluster(d, data_len) ParseClientDataCluster(d, dataLen)
default: default:
// Assert() once all functions are implemented and tested. // Assert() once all functions are implemented and tested.
d.FieldRawLen("data", data_len*8) d.FieldRawLen("data", dataLen*8)
return return
} }
}) })

View File

@ -12,46 +12,46 @@ func ParseClientInfo(d *decode.D, length int64) {
d.FieldStruct("client_info", func(d *decode.D) { d.FieldStruct("client_info", func(d *decode.D) {
pos := d.Pos() pos := d.Pos()
var ( var (
is_unicode bool isUnicode bool
has_null bool hasNull bool
null_n uint64 = 0 nullN uint64 = 0
unicode_n uint64 = 0 unicodeN uint64 = 0
) )
code_page := d.FieldU32("code_page") codePage := d.FieldU32("code_page")
flags := d.U32() flags := d.U32()
d.SeekRel(-4 * 8) d.SeekRel(-4 * 8)
d.FieldStruct("flags", decodeFlagsFn) d.FieldStruct("flags", decodeFlagsFn)
is_unicode = ((flags & INFO_UNICODE) != 0) isUnicode = ((flags & INFO_UNICODE) != 0)
has_null = (code_page == 1252 || is_unicode) hasNull = (codePage == 1252 || isUnicode)
if has_null { if hasNull {
null_n = 1 nullN = 1
} }
if is_unicode { if isUnicode {
unicode_n = 2 unicodeN = 2
} }
domain_length := int(d.FieldU16("domain_length") + null_n*unicode_n) domainLength := int(d.FieldU16("domain_length") + nullN*unicodeN)
username_length := int(d.FieldU16("username_length") + null_n*unicode_n) usernameLength := int(d.FieldU16("username_length") + nullN*unicodeN)
password_length := int(d.FieldU16("password_length") + null_n*unicode_n) passwordLength := int(d.FieldU16("password_length") + nullN*unicodeN)
alternate_shell_length := int(d.FieldU16("alternate_shell_length") + null_n*unicode_n) alternateShellLength := int(d.FieldU16("alternate_shell_length") + nullN*unicodeN)
working_dir_length := int(d.FieldU16("working_dir_length") + null_n*unicode_n) workingDirLength := int(d.FieldU16("working_dir_length") + nullN*unicodeN)
d.FieldUTF16LE("domain", domain_length, scalar.StrActualTrim("\x00")) d.FieldUTF16LE("domain", domainLength, scalar.StrActualTrim("\x00"))
d.FieldUTF16LE("username", username_length, scalar.StrActualTrim("\x00")) d.FieldUTF16LE("username", usernameLength, scalar.StrActualTrim("\x00"))
d.FieldUTF16LE("password", password_length, scalar.StrActualTrim("\x00")) d.FieldUTF16LE("password", passwordLength, scalar.StrActualTrim("\x00"))
d.FieldUTF16LE("alternate_shell", alternate_shell_length, scalar.StrActualTrim("\x00")) d.FieldUTF16LE("alternate_shell", alternateShellLength, scalar.StrActualTrim("\x00"))
d.FieldUTF16LE("working_dir", working_dir_length, scalar.StrActualTrim("\x00")) d.FieldUTF16LE("working_dir", workingDirLength, scalar.StrActualTrim("\x00"))
extra_length := length - ((d.Pos() - pos) / 8) extraLength := length - ((d.Pos() - pos) / 8)
if extra_length > 0 { if extraLength > 0 {
d.FieldStruct("extra_info", func(d *decode.D) { d.FieldStruct("extra_info", func(d *decode.D) {
d.FieldU16("address_family", scalar.UintHex) d.FieldU16("address_family", scalar.UintHex)
address_length := int(d.FieldU16("address_length")) addressLength := int(d.FieldU16("address_length"))
d.FieldUTF16LE("address", address_length, scalar.StrActualTrim("\x00")) d.FieldUTF16LE("address", addressLength, scalar.StrActualTrim("\x00"))
client_dir_length := int(d.FieldU16("client_dir_length")) clientDirLength := int(d.FieldU16("client_dir_length"))
d.FieldUTF16LE("client_dir", client_dir_length, scalar.StrActualTrim("\x00")) d.FieldUTF16LE("client_dir", clientDirLength, scalar.StrActualTrim("\x00"))
// TS_TIME_ZONE_INFORMATION structure // TS_TIME_ZONE_INFORMATION structure
// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/526ed635-d7a9-4d3c-bbe1-4e3fb17585f4 // https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpbcgr/526ed635-d7a9-4d3c-bbe1-4e3fb17585f4
d.FieldU32("timezone_bias") d.FieldU32("timezone_bias")
@ -92,14 +92,14 @@ const (
func decodeFlagsFn(d *decode.D) { func decodeFlagsFn(d *decode.D) {
d.FieldBool("mouse") d.FieldBool("mouse")
d.FieldBool("disabledctrlaltdel") d.FieldBool("disabledctrlaltdel")
d.SeekRel(1) d.FieldRawLen("unused0", 1)
d.FieldBool("autologon") d.FieldBool("autologon")
d.FieldBool("unicode") d.FieldBool("unicode")
d.FieldBool("maximizeshell") d.FieldBool("maximizeshell")
d.FieldBool("logonnotify") d.FieldBool("logonnotify")
d.FieldBool("compression") d.FieldBool("compression")
d.FieldBool("enablewindowskey") d.FieldBool("enablewindowskey")
d.SeekRel(4) d.FieldRawLen("unused1", 4)
d.FieldBool("remoteconsoleaudio") d.FieldBool("remoteconsoleaudio")
d.FieldBool("force_encrypted_cs_pdu") d.FieldBool("force_encrypted_cs_pdu")
d.FieldBool("rail") d.FieldBool("rail")
@ -113,6 +113,5 @@ func decodeFlagsFn(d *decode.D) {
d.FieldBool("reserved1") d.FieldBool("reserved1")
d.FieldBool("reserved2") d.FieldBool("reserved2")
d.FieldBool("hidef_rail_supported") d.FieldBool("hidef_rail_supported")
d.FieldRawLen("unused2", 6)
d.SeekRel(d.Pos() % 31)
} }

View File

@ -30,24 +30,24 @@ const (
) )
var cbTypesMap = scalar.UintMapSymStr{ var cbTypesMap = scalar.UintMapSymStr{
CB_MONITOR_READY: "cb_monitor_ready", CB_MONITOR_READY: "monitor_ready",
CB_FORMAT_LIST: "cb_format_list", CB_FORMAT_LIST: "format_list",
CB_FORMAT_LIST_RESPONSE: "cb_format_list_response", CB_FORMAT_LIST_RESPONSE: "format_list_response",
CB_FORMAT_DATA_REQUEST: "cb_format_data_request", CB_FORMAT_DATA_REQUEST: "format_data_request",
CB_FORMAT_DATA_RESPONSE: "cb_format_data_response", CB_FORMAT_DATA_RESPONSE: "format_data_response",
CB_TEMP_DIRECTORY: "cb_temp_directory", CB_TEMP_DIRECTORY: "temp_directory",
CB_CLIP_CAPS: "cb_clip_caps", CB_CLIP_CAPS: "clip_caps",
CB_FILECONTENTS_REQUEST: "cb_filecontents_request", CB_FILECONTENTS_REQUEST: "filecontents_request",
CB_FILECONTENTS_RESPONSE: "cb_filecontents_response", CB_FILECONTENTS_RESPONSE: "filecontents_response",
CB_LOCK_CLIPDATA: "cb_lock_clipdata", CB_LOCK_CLIPDATA: "lock_clipdata",
CB_UNLOCK_CLIPDATA: "cb_unlock_clipdata", CB_UNLOCK_CLIPDATA: "unlock_clipdata",
} }
var cbFlagsMap = scalar.UintMapSymStr{ var cbFlagsMap = scalar.UintMapSymStr{
NONE: "none", NONE: "none",
CB_RESPONSE_OK: "cb_response_ok", CB_RESPONSE_OK: "response_ok",
CB_RESPONSE_FAIL: "cb_response_fail", CB_RESPONSE_FAIL: "response_fail",
CB_ASCII_NAMES: "cb_ascii_names", CB_ASCII_NAMES: "ascii_names",
} }
var cbParseFnMap = map[uint16]interface{}{ var cbParseFnMap = map[uint16]interface{}{
@ -56,20 +56,20 @@ var cbParseFnMap = map[uint16]interface{}{
func ParseClipboardData(d *decode.D, length int64) { func ParseClipboardData(d *decode.D, length int64) {
d.FieldStruct("clipboard_data", func(d *decode.D) { d.FieldStruct("clipboard_data", func(d *decode.D) {
msg_type := uint16(d.FieldU16("msg_type", cbTypesMap)) msgType := uint16(d.FieldU16("msg_type", cbTypesMap))
d.FieldU16("msg_flags", cbFlagsMap) d.FieldU16("msg_flags", cbFlagsMap)
data_length := d.FieldU32("data_len") dataLength := d.FieldU32("data_len")
cbParser, ok := cbParseFnMap[msg_type] cbParser, ok := cbParseFnMap[msgType]
if ok { if ok {
parseFn, ok := cbParser.(func(d *decode.D, length uint64)) parseFn, ok := cbParser.(func(d *decode.D, length uint64))
if ok { if ok {
parseFn(d, data_length) parseFn(d, dataLength)
return return
} }
} }
// Assert() once all functions are implemented. // Assert() once all functions are implemented.
d.FieldRawLen("data", int64(data_length*8)) d.FieldRawLen("data", int64(dataLength*8))
}) })
} }

View File

@ -67,9 +67,9 @@ func ParseFastPathInput(d *decode.D, length int64) {
} }
}) })
input_length := d.FieldU8("input_length1", scalar.UintHex) inputLength := d.FieldU8("input_length1", scalar.UintHex)
if input_length&0x80 != 0 { if inputLength&0x80 != 0 {
input_length = ((input_length & 0x7f) << 8) | d.FieldU8("input_length2", scalar.UintHex) inputLength = ((inputLength & 0x7f) << 8) | d.FieldU8("input_length2", scalar.UintHex)
} }
// d.FieldU64("data_signature", scalar.Hex) // d.FieldU64("data_signature", scalar.Hex)
@ -92,9 +92,9 @@ func ParseFastPathInput(d *decode.D, length int64) {
// } // }
// }) // })
input_length -= uint64(d.Pos()-pos) / 8 inputLength -= uint64(d.Pos()-pos) / 8
if input_length > 0 { if inputLength > 0 {
d.FieldRawLen("data", int64(input_length*8)) d.FieldRawLen("data", int64(inputLength*8))
} }
}) })
} }

View File

@ -10,6 +10,7 @@
package pyrdp package pyrdp
import ( import (
"embed"
"time" "time"
"github.com/wader/fq/format" "github.com/wader/fq/format"
@ -19,6 +20,19 @@ import (
"github.com/wader/fq/pkg/scalar" "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 ( const (
READ_EXTRA = true READ_EXTRA = true
@ -46,26 +60,26 @@ const (
) )
var pduTypesMap = scalar.UintMapSymStr{ var pduTypesMap = scalar.UintMapSymStr{
PDU_FAST_PATH_INPUT: "pdu_fastpath_input", PDU_FAST_PATH_INPUT: "fastpath_input",
PDU_FAST_PATH_OUTPUT: "pdu_fastpath_output", PDU_FAST_PATH_OUTPUT: "fastpath_output",
PDU_CLIENT_INFO: "pdu_client_info", PDU_CLIENT_INFO: "client_info",
PDU_SLOW_PATH_PDU: "pdu_slow_path_pdu", PDU_SLOW_PATH_PDU: "slow_path_pdu",
PDU_CONNECTION_CLOSE: "pdu_connection_close", PDU_CONNECTION_CLOSE: "connection_close",
PDU_CLIPBOARD_DATA: "pdu_clipboard_data", PDU_CLIPBOARD_DATA: "clipboard_data",
PDU_CLIENT_DATA: "pdu_client_data", PDU_CLIENT_DATA: "client_data",
PDU_MOUSE_MOVE: "pdu_mouse_move", PDU_MOUSE_MOVE: "mouse_move",
PDU_MOUSE_BUTTON: "pdu_mouse_button", PDU_MOUSE_BUTTON: "mouse_button",
PDU_MOUSE_WHEEL: "pdu_mouse_wheel", PDU_MOUSE_WHEEL: "mouse_wheel",
PDU_KEYBOARD: "pdu_keyboard", PDU_KEYBOARD: "keyboard",
PDU_TEXT: "pdu_text", PDU_TEXT: "text",
PDU_FORWARDING_STATE: "pdu_forwarding_state", PDU_FORWARDING_STATE: "forwarding_state",
PDU_BITMAP: "pdu_bitmap", PDU_BITMAP: "bitmap",
PDU_DEVICE_MAPPING: "pdu_device_mapping", PDU_DEVICE_MAPPING: "device_mapping",
PDU_DIRECTORY_LISTING_REQUEST: "pdu_directory_listing_request", PDU_DIRECTORY_LISTING_REQUEST: "directory_listing_request",
PDU_DIRECTORY_LISTING_RESPONSE: "pdu_directory_listing_response", PDU_DIRECTORY_LISTING_RESPONSE: "directory_listing_response",
PDU_FILE_DOWNLOAD_REQUEST: "pdu_file_download_request", PDU_FILE_DOWNLOAD_REQUEST: "file_download_request",
PDU_FILE_DOWNLOAD_RESPONSE: "pdu_file_download_response", PDU_FILE_DOWNLOAD_RESPONSE: "file_download_response",
PDU_FILE_DOWNLOAD_COMPLETE: "pdu_file_download_complete", PDU_FILE_DOWNLOAD_COMPLETE: "file_download_complete",
} }
var pduParsersMap = map[uint16]interface{}{ var pduParsersMap = map[uint16]interface{}{
@ -91,15 +105,6 @@ var pduParsersMap = map[uint16]interface{}{
// PDU_FILE_DOWNLOAD_COMPLETE: pyrdp_pdu.ParseFileDownloadComplete, // PDU_FILE_DOWNLOAD_COMPLETE: pyrdp_pdu.ParseFileDownloadComplete,
} }
func init() {
interp.RegisterFormat(
format.PYRDP,
&decode.Format{
Description: "PyRDP Replay Files",
DecodeFn: decodePYRDP,
})
}
func decodePYRDP(d *decode.D) any { func decodePYRDP(d *decode.D) any {
d.Endian = decode.LittleEndian d.Endian = decode.LittleEndian
@ -109,14 +114,14 @@ func decodePYRDP(d *decode.D) any {
pos := d.Pos() pos := d.Pos()
size := d.FieldU64("size") // minus the length size := d.FieldU64("size") // minus the length
pdu_type := uint16(d.FieldU16("pdu_type", pduTypesMap)) pduType := uint16(d.FieldU16("pdu_type", pduTypesMap))
d.FieldU64("timestamp", timestampMapper) d.FieldU64("timestamp", scalar.UintActualUnixTimeDescription(time.Millisecond, time.RFC3339Nano))
pdu_size := int64(size - 18) pduSize := int64(size - 18)
pduParser, ok := pduParsersMap[pdu_type] pduParser, ok := pduParsersMap[pduType]
if !ok { // catch undeclared parsers if !ok { // catch undeclared parsers
if pdu_size > 0 { if pduSize > 0 {
d.FieldRawLen("data", pdu_size*8) d.FieldRawLen("data", pduSize*8)
} }
return return
} }
@ -124,7 +129,7 @@ func decodePYRDP(d *decode.D) any {
if !ok { if !ok {
return return
} }
parseFn(d, pdu_size) parseFn(d, pduSize)
curr := d.Pos() - pos curr := d.Pos() - pos
if READ_EXTRA { if READ_EXTRA {
@ -139,8 +144,3 @@ func decodePYRDP(d *decode.D) any {
} }
func noParse(d *decode.D, length int64) {} func noParse(d *decode.D, length int64) {}
var timestampMapper = scalar.UintFn(func(s scalar.Uint) (scalar.Uint, error) {
s.Sym = time.UnixMilli(int64(s.Actual)).UTC().String()
return s, nil
})

6
format/pyrdp/pyrdp.md Normal file
View File

@ -0,0 +1,6 @@
### Authors
- Olivier Bilodeau <olivier.bilodeau@flare.io>, Maintainer
- Lisandro Ubiedo, Author
### References
- https://github.com/GoSecure/pyrdp

File diff suppressed because it is too large Load Diff

8
go.mod
View File

@ -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
View File

@ -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=