Blog

  • PLC5 – CSPv4 Wireshark Dissector

    Recently I had been looking at PCAP traces of a PLC5 communicating with RsLinx. Wireshark just saw it as a blob of data on top of the TCP header. Well this just would not do. Wireshark provides a nice interface for using LUA to write your own dissector. This is what I ended up doing for the CSPv4 data (which is actually CSPv4 Header + LSAP + PCCC or PC cubed). An added bonus of writing a dissector for an unknown protocol is that the protocol filter will also register the bytes you define, so you can easily filter a packet stream with your newly defined byte fields.

    A big thanks to these two articles from Lynn’s Iatips, specifically:

    As well as the Rockwell document that provided valuable PCCC format information (Chapter 6,7):

    Wireshark Dissector for PLC5 – CSPv4 + LSAP + PCCC

    Without further ado – the LUA code for the Wireshark dissector. Following this code include is a screenshot and instructions of how to include this parser within Wireshark.

    -- CSPv4 Parser --------------------------------
    --
    -- Date: July 25, 2012
    -- Author: Erik Schweigert
    -- E-mail: erik@linuxtips.ca
    --
    -- Purpose: To decode the CSPv4 Packet
    -- CSPv4 + LSAP + PCCC
    ------------------------------------------------
    p_cspv4 = Proto("cspv4","CSPv4")
    p_lsap = Proto("lsap","LSAP")
    p_pccc = Proto("pccc","PCCC")

    -- ----------------- CSPv4 Header ------------
    local f_mode = ProtoField.uint8("cspv4.mode", "Mode", base.HEX)
    local f_submode = ProtoField.uint8("cspv4.submode", "Submode", base.HEX)
    local f_data_length = ProtoField.uint16("cspv4.data_length", "Data Length", base.HEX)
    local f_conn_id = ProtoField.uint32("cspv4.conn_id", "Connection ID [slave/server]", base.HEX)
    local f_status = ProtoField.uint32("cspv4.status", "Status", base.HEX)
    local f_context = ProtoField.bytes("cspv4.context", "Context", base.HEX)
    -- ---------------- End CSPv4 Header -----------

    -- ------------------ LSAP ---------------------
    -- Local
    local f_dest = ProtoField.uint8("cspv4.dst", "Destination Byte", base.HEX)
    local f_res5 = ProtoField.uint8("cspv4.res5", "Control Byte", base.HEX)
    local f_src = ProtoField.uint8("cspv4.src", "Source Byte [Master Address]", base.HEX)
    local f_lsap = ProtoField.uint8("cspv4.lsap", "LSAP", base.HEX)

    -- Remote
    local f_resX = ProtoField.uint8("cspv4.resX", "Mystery Byte", base.HEX)
    local f_dst_link = ProtoField.uint16("cspv4.dst_link","Destination Link Address", base.HEX)
    local f_dst_station = ProtoField.uint16("cspv4.dst_station", "Destination Station Address", base.HEX)
    local f_resY = ProtoField.uint8("cspv4.resY", "Mystery Byte 2", base.HEX)
    local f_src_link = ProtoField.uint16("cspv4.src_link", "Source Link Address", base.HEX)
    local f_src_station = ProtoField.uint16("cspv4.src_station", "Source Station Address", base.HEX)
    local f_resZ = ProtoField.uint8("cspv4.resZ", "Mystery Byte 3", base.HEX)
    -- ------------------ End LSAP ------------------

    -- ------------------ PCCC ----------------------
    local f_pccc_command = ProtoField.uint8("cspv4.pccc_command", "Command Code", base.HEX)
    local f_pccc_sts = ProtoField.uint8("cspv4.pccc_sts", "Status Code", base.HEX)
    local f_pccc_tns = ProtoField.uint16("cspv4.pccc_tns", "Transaction Number", base.HEX)
    local f_pccc_fnc = ProtoField.uint8("cspv4.pccc_fnc", "Function Code", base.HEX)
    local f_pccc_addr = ProtoField.uint16("cspv4.pccc_addr", "Address of Memory Location", base.HEX)
    local f_pccc_size = ProtoField.uint8("cspv4.pccc_size", "Size", base.HEX)
    local f_pccc_data = ProtoField.bytes("cspv4.pccc_data", "Data", base.HEX)
    -- ------------------ End PCCC -------------------

    -- CSPv4 Fields
    p_cspv4.fields = {f_mode}
    p_cspv4.fields = {f_submode}
    p_cspv4.fields = {f_data_length}
    p_cspv4.fields = {f_conn_id}
    p_cspv4.fields = {f_status}
    p_cspv4.fields = {f_context}
    p_cspv4.fields = {f_dest}
    p_cspv4.fields = {f_res5}
    p_cspv4.fields = {f_src}
    p_cspv4.fields = {f_lsap}

    -- Remote LSAP Fields
    p_cspv4.fields = {f_resX}
    p_cspv4.fields = {f_dst_link}
    p_cspv4.fields = {f_dst_station}
    p_cspv4.fields = {f_resY}
    p_cspv4.fields = {f_src_link}
    p_cspv4.fields = {f_src_station}
    p_cspv4.fields = {f_resZ}

    -- PCCC Fields
    p_cspv4.fields = {f_pccc_command}
    p_cspv4.fields = {f_pccc_sts}
    p_cspv4.fields = {f_pccc_tns}
    p_cspv4.fields = {f_pccc_fnc}
    p_cspv4.fields = {f_pccc_addr}
    p_cspv4.fields = {f_pccc_size}
    p_cspv4.fields = {f_pccc_data}

    function build_cspv4_header(buf)
    build_request(buf)
    build_submode(buf)

    subtree:add(f_data_length, buf(2,2))
    subtree:add(f_conn_id, buf(4,4))
    subtree:add(f_status, buf(8,4))
    subtree:add(f_context, buf(12,16))
    end

    function build_request(buf)
    if buf(0,1):uint() == 1 then
    subtree:add(f_mode, buf(0,1)):append_text(" (Request)")
    elseif buf(0,1):uint() == 2 then
    subtree:add(f_mode, buf(0,1)):append_text(" (Response)")
    else
    subtree:add(f_mode, buf(0,1))
    end
    end

    function build_submode(buf)
    if buf(1,1):uint() == 1 then
    subtree:add(f_submode, buf(1,1)):append_text(" (Connection)")
    elseif buf(1,1):uint() == 7 then
    subtree:add(f_submode, buf(1,1)):append_text(" (PCCC)")
    else
    subtree:add(f_submode, buf(1,1))
    end
    end

    function build_lsap(buf, root)

    lsap_tree = root:add(p_lsap, buf(28))

    lsap_tree:add(f_dest, buf(28,1))
    lsap_tree:add(f_res5, buf(29,1))
    lsap_tree:add(f_src, buf(30,1))

    if buf(31,1):uint() == 0 then
    lsap_tree:add(f_lsap, buf(31,1)):append_text(" (Local Form)")
    elseif buf(31,1):uint() == 1 then
    lsap_tree:add(f_lsap, buf(31,1)):append_text(" (Remote Form)")
    build_lsap_remote(buf, lsap_tree)
    else
    lsap_tree:add(f_lsap, buf(31,1))
    end
    end

    function build_lsap_remote(buf, lsap_tree)
    lsap_tree:add(f_resX, buf(32,1))
    lsap_tree:add(f_dst_link, buf(33,2))
    lsap_tree:add(f_dst_station, buf(35,2))
    lsap_tree:add(f_resY, buf(37,1))
    lsap_tree:add(f_src_link, buf(38,2))
    lsap_tree:add(f_src_station, buf(40,2))
    lsap_tree:add(f_resZ, buf(42,1))
    end

    function build_pccc(buf, root)

    pccc_tree = root:add(p_pccc, buf(32))

    -- Ensure its PCCCC
    if buf(1,1):uint() ~= 7 then end

    if buf(31,1):uint() == 1 then
    offset = 11
    else
    offset = 0
    end

    pccc_tree:add(f_pccc_command, buf(32 + offset, 1))
    pccc_tree:add(f_pccc_sts, buf(33 + offset, 1))
    pccc_tree:add(f_pccc_tns, buf(34 + offset, 2))
    pccc_tree:add(f_pccc_fnc, buf(36 + offset, 1))
    pccc_tree:add(f_pccc_addr, buf(37 + offset, 2))
    pccc_tree:add(f_pccc_size, buf(39 + offset, 1))
    pccc_tree:add(f_pccc_data, buf(40 + offset, buf:len() - (40 + offset)))
    end

    -- cspv4 dissector function
    function p_cspv4.dissector (buf, pkt, root)
    -- validate packet length is adequate, otherwise quit
    if buf:len() == 0 then return end

    pkt.cols.protocol = p_cspv4.name

    -- create subtree for cspv4
    subtree = root:add(p_cspv4, buf(0))
    -- add protocol fields to subtree

    build_cspv4_header(buf)
    build_lsap(buf, root)
    build_pccc(buf, root)

    -- description of payload
    subtree:set_text("CSPv4, CSPv4 Header Information")

    -- add debug info if debug field is not nil
    if f_debug then
    -- write debug values
    subtree:add(f_debug, buf:len())
    end
    end

    -- Initialization routine
    function p_cspv4.init()
    end

    -- register a chained dissector for port 2222
    local tcp_dissector_table = DissectorTable.get("tcp.port")
    dissector = tcp_dissector_table:get_dissector(2222)
    -- you can call dissector from function p_cspv4.dissector above
    -- so that the previous dissector gets called
    tcp_dissector_table:add(2222, p_cspv4)

    As you can see there is nothing ground breaking in this parser, and the code itself is quite rudimentary. A great enhancement would be to add the textual value of what the PCCC command vs function code actually equates to (read bit, write bit, etc).

    The results of installing the LUA code above to decipher the PLC5 – CSPv4 data is:

    Installing LUA Dissector to Wireshark

    1. Save the lua script above to any folder and call the file cspv4.lua
    2. Open init.lua in the Wireshark installation directory for editing. In Linux it can be found in /etc/wireshark/init.lua.  You will need Admin privileges on Windows Vista and 7.
    3. Comment out the following line in init.lua (single line comments begin with --):1 disable_lua = true; do return end;
    4. Add the following lines to init.lua (at the very end):1 dofile(“/path/to/the/file/cspv4.lua”)
    5. Run Wireshark
    6. Load a capture file that has the packets of your custom protocol or start a live capture.

    Now you have enhanced Wireshark to properly dissect your PLC5 packets – at least if they are CSPv4 with PCCC.

  • Title: Unlocking the Power of Linux Kernel: A Comprehensive Guide to the Heart of Linux

    Are you ready to dive into the fascinating world of Linux and explore the core that makes it all tick? Look no further! The Linux Kernel is the backbone of the Linux operating system, and understanding its intricacies can take your computing experience to the next level. In this blog post, we’ll delve into the world of Linux Kernel, exploring its history, architecture, and features, as well as providing valuable tips and tricks for getting the most out of your Linux system.

    Introduction to Linux Kernel

    The Linux Kernel is the core part of the Linux operating system, responsible for managing the system’s hardware resources and providing services to applications. It’s the layer between the hardware and the user space, handling tasks such as process scheduling, memory management, and input/output operations. The Kernel is written in C and assembly language, and its source code is freely available under the GNU General Public License (GPL). With a rich history dating back to 1991, the Linux Kernel has evolved significantly over the years, with contributions from thousands of developers worldwide.

    Linux Kernel Architecture

    The Linux Kernel architecture is modular, consisting of several key components that work together to provide a robust and efficient operating system. The Kernel can be divided into several layers, including:

    • Hardware Abstraction Layer (HAL): provides a standardized interface to the hardware, allowing the Kernel to interact with different hardware components.
    • Device Drivers: manage the interaction between the Kernel and hardware devices, such as network cards, sound cards, and graphics cards.
    • System Call Interface: provides a interface for applications to interact with the Kernel, allowing them to request services such as process creation, file access, and network communication.
    • Process Scheduler: responsible for managing the execution of processes, allocating CPU time and resources as needed.
    • Understanding the Linux Kernel architecture is essential for optimizing system performance, troubleshooting issues, and developing custom Kernel modules. By grasping the relationships between these components, you’ll be better equipped to tackle complex system administration tasks and take advantage of the Linux Kernel’s flexibility.

      Linux Kernel Features and Tools

      The Linux Kernel offers a wide range of features and tools that make it an attractive choice for developers, administrators, and power users. Some of the key features include:

    • Virtualization: allows multiple operating systems to run on a single physical machine, providing improved resource utilization and flexibility.
    • Networking: provides a robust and scalable networking stack, supporting a wide range of protocols and devices.
    • Security: includes a range of security features, such as access control lists (ACLs), SELinux, and AppArmor, to protect the system from unauthorized access and malicious activity.
    • File Systems: supports a variety of file systems, including ext4, XFS, and Btrfs, each with its own strengths and weaknesses.
    • In addition to these features, the Linux Kernel provides a range of tools and utilities for system administration, debugging, and optimization. Some of the most popular tools include:

    • Sysctl: allows administrators to tune Kernel parameters and settings in real-time.
    • Dmesg: provides a record of Kernel messages and errors, helping with troubleshooting and debugging.
    • Kexec: enables administrators to load a new Kernel image without rebooting the system.
    • Customizing and Optimizing the Linux Kernel

      One of the key advantages of the Linux Kernel is its customizability. By compiling a custom Kernel, you can tailor the operating system to your specific needs, optimizing performance, and reducing unnecessary overhead. To get started with customizing the Linux Kernel, you’ll need to:

    • Obtain the Kernel source code: download the latest Kernel source code from the official Linux Kernel repository.
    • Configure the Kernel: use tools such as `make menuconfig` or `make xconfig` to select the desired features and options.
    • Compile the Kernel: build the custom Kernel image using the `make` command.
    • Install the Kernel: install the custom Kernel image on your system, either manually or using a package manager.
    • By customizing the Linux Kernel, you can achieve significant performance gains, improved security, and enhanced functionality. However, keep in mind that compiling a custom Kernel requires a good understanding of the underlying architecture and configuration options.

      Conclusion and Key Takeaways

      In conclusion, the Linux Kernel is a powerful and flexible core that underlies the Linux operating system. By understanding its architecture, features, and tools, you can unlock the full potential of your Linux system, optimizing performance, security, and functionality. Some key takeaways from this guide include:

    • The Linux Kernel is modular and customizable: allowing you to tailor the operating system to your specific needs.
    • Understanding the Kernel architecture is essential: for optimizing system performance, troubleshooting issues, and developing custom Kernel modules.
    • The Linux Kernel provides a range of features and tools: for virtualization, networking, security, and file systems, making it an attractive choice for developers, administrators, and power users.
    • Customizing the Linux Kernel can achieve significant performance gains: by optimizing the operating system for your specific use case.

    Whether you’re a seasoned Linux administrator or just starting to explore the world of Linux, this guide has provided you with a comprehensive overview of the Linux Kernel. By applying the knowledge and techniques outlined in this post, you’ll be well on your way to unlocking the full potential of your Linux system and becoming a Linux power user.

  • The first post

    Well this is new, I havent used WordPress in a long time and it appears to have expanded in leaps and bounds. Exciting things to come!