You're given a picture of a Lego Mindstorms EV3 display block with the flag partially displayed on it. You're also given a macOS PacketLogger file.
If you open the PacketLogger file, you'll find a capture of packets as they were being sent back and forth to the device. You can export that to a format that's easier to write a parser for via File -> Export -> Payload as Text...
Once you do that, you can use the [EV3 developer kit documentation](https://education.lego.com/en-us/support/mindstorms-ev3/developer-kits) to find the specifications for the protocol used. To get the flag, you only need to parse outgoing packets, and you only really need to pay attention to one thing: the `TEXT` command of the `opUI_DRAW` instruction.
We can write a crude Go parser like so:
```gopackage main
import (	"bufio"	"encoding/binary"	"encoding/hex"	"fmt"	"os"	"sort"	"strings")
func parseParameter(b *[]byte) interface{} {	switch (*b)[0] & 0xc0 {	case 0:		// short constant		var ret int		if (*b)[0]&0x20 == 0 {			// positive			ret = int((*b)[0] & 0x1f)		} else {			// negative			ret = -int((*b)[0] & 0x1f)		}		*b = (*b)[1:]		return ret	case 0x80:		// long constant		if (*b)[0]&0xf0 == 0x80 {			// value			switch (*b)[0] & 0x07 {			case 0, 4:				// null-terminated				s := ""				*b = (*b)[1:]				for (*b)[0] != 0 {					s += string(rune((*b)[0]))					*b = (*b)[1:]				}				*b = (*b)[1:]				return s			case 1:				// 1 byte				ret := (*b)[1]				*b = (*b)[2:]				return int(ret)			case 2:				// 2 bytes				ret := binary.LittleEndian.Uint16((*b)[1:])				*b = (*b)[3:]				return int(ret)			case 3:				// 4 bytes				ret := binary.LittleEndian.Uint32((*b)[1:])				*b = (*b)[5:]				return int(ret)			}		}	}	return nil}
func main() {	f, err := os.Open("Extracted Data/RFCOMM-Oct 18 16_06_54.995.txt")	if err != nil {		panic(err)	}	defer f.Close()
	type Text struct {		X int		Y int		S string	}	var texts []Text
	scanner := bufio.NewScanner(f)	for scanner.Scan() {		line := scanner.Text()		if !strings.HasPrefix(line, "0B EF") {			continue		}		line = strings.Replace(line[9:], " ", "", -1)		b, err := hex.DecodeString(line)		if err != nil {			panic(err)		}		byteCodes := b[7:]		byteCodes = byteCodes[:len(byteCodes)-2]
		for len(byteCodes) > 0 {			switch byteCodes[0] {			case 0x80:				// FLUSH				byteCodes = byteCodes[1:]			case 0x84:				// DRAW				switch byteCodes[1] {				case 0x00:					// UPDATE					byteCodes = byteCodes[2:]				case 0x05:					// TEXT					byteCodes = byteCodes[2:]					parseParameter(&byteCodes)					x := parseParameter(&byteCodes).(int)					y := parseParameter(&byteCodes).(int)					s := parseParameter(&byteCodes).(string)					texts = append(texts, Text{x, y, s})				case 0x12:					// TOPLINE					byteCodes = byteCodes[3:]				case 0x13:					// FILLWINDOW					byteCodes = byteCodes[4:]				default:					panic(fmt.Errorf("unexpected byte code: %x", byteCodes[1]))				}			default:				panic(fmt.Errorf("unexpected byte code: %x", byteCodes[0]))			}		}	}
	if err := scanner.Err(); err != nil {		panic(err)	}
	sort.Slice(texts, func(i, j int) bool {		if texts[i].Y < texts[j].Y {			return true		}		if texts[i].Y == texts[j].Y {			return texts[i].X < texts[j].X		}		return false	})
	y := 0	for _, t := range texts {		if t.Y != y {			fmt.Printf("\n")			y = t.Y		}		fmt.Printf("%s", t.S)	}	fmt.Printf("\n")}```
The result:
```hitcon{m1nd5t0rm_communication_and_firmware_developer_kit}```