Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dhcp.py: decode error "object has no attribute 'encode'" #1633

Open
emdete opened this issue Oct 16, 2023 · 3 comments · May be fixed by #1858
Open

dhcp.py: decode error "object has no attribute 'encode'" #1633

emdete opened this issue Oct 16, 2023 · 3 comments · May be fixed by #1858
Assignees
Labels
bug Unexpected problem or unintended behavior

Comments

@emdete
Copy link

emdete commented Oct 16, 2023

Configuration

impacket version: HEAD
Python version: 3.11
Target OS: Linux

Debug Output With Command String

		dhcp = DhcpPacket(buffer)
		print(dhcp)
Traceback (most recent call last):
  File "/home/mdt/Source/emdete/honeypot/snooper/main.py", line 14, in learn_dhcp
    dhcp = DHCP(buffer)
           ^^^^^^^^^^^^
  File "/home/mdt/Source/oss/python/impacket/impacket/dhcp.py", line 148, in __init__
    structure.Structure.__init__(self, data, alignment)
  File "/home/mdt/Source/oss/python/impacket/impacket/structure.py", line 87, in __init__
    self.fromString(data)
  File "/home/mdt/Source/oss/python/impacket/impacket/structure.py", line 152, in fromString
    self[field[0]] = self.unpack(field[1], data[:size], dataClassOrCode = dataClassOrCode, field = field[0])
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/mdt/Source/oss/python/impacket/impacket/structure.py", line 307, in unpack
    return eval(dataClassOrCode, {}, fields)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<string>", line 1, in <module>
  File "/home/mdt/Source/oss/python/impacket/impacket/dhcp.py", line 179, in unpackOptions
    value = self.unpack(format, options[i+2:i+2+size])
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/mdt/Source/oss/python/impacket/impacket/structure.py", line 382, in unpack
    return dataClassOrCode(data)
           ^^^^^^^^^^^^^^^^^^^^^
  File "/usr/lib/python3/dist-packages/six.py", line 644, in b
    return s.encode("latin-1")
           ^^^^^^^^
AttributeError: ("'bytearray' object has no attribute 'encode'", "When unpacking field 'options | _ | b''[:0]'")

PCAP

 b'\x01\x01\x06\x00\xa3Y\xdf\x06\x00\x06\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf84A\xdb2.\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00c\x82Sc5\x01\x032\x04\xc0\xa8\x00\x8c6\x04\xc0\xa8\x00\x019\x02\x02@7\x07\x01\x03\x06\x0c\x0f\x1c*<\x0cudhcp 1.36.1=\x07\x01\xf84A\xdb2.\xff\x00\x00\x00\x00\x00\x00\x00\x00'

Additional context

@emdete
Copy link
Author

emdete commented Oct 16, 2023

it seems the line 381 in impacket/structure.py should read:

if (isinstance(data, bytes) or isinstance(data, bytearray)) and dataClassOrCode is b:

because the buffer is not bytes but bytearray. fixing this leads to the next error:

Traceback (most recent call last):
  File "/home/mdt/Source/emdete/honeypot/snooper/main.py", line 14, in learn_dhcp
    dhcp = DhcpPacket(buffer)
           ^^^^^^^^^^^^^^^^^^
  File "/home/mdt/Source/oss/python/impacket/impacket/dhcp.py", line 148, in __init__
    structure.Structure.__init__(self, data, alignment)
  File "/home/mdt/Source/oss/python/impacket/impacket/structure.py", line 87, in __init__
    self.fromString(data)
  File "/home/mdt/Source/oss/python/impacket/impacket/structure.py", line 152, in fromString
    self[field[0]] = self.unpack(field[1], data[:size], dataClassOrCode = dataClassOrCode, field = field[0])
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/mdt/Source/oss/python/impacket/impacket/structure.py", line 307, in unpack
    return eval(dataClassOrCode, {}, fields)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "<string>", line 1, in <module>
  File "/home/mdt/Source/oss/python/impacket/impacket/dhcp.py", line 179, in unpackOptions
    value = self.unpack(format, options[i+2:i+2+size])
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/mdt/Source/oss/python/impacket/impacket/structure.py", line 386, in unpack
    return unpack(format, data)[0]
           ^^^^^^^^^^^^^^^^^^^^
struct.error: ('unpack requires a buffer of 4 bytes', "When unpacking field 'options | _ | b''[:0]'")

@anadrianmanrique anadrianmanrique added the in review This issue or pull request is being analyzed label Oct 19, 2023
@zmw12306
Copy link

I also got this error, here is my code:

import struct
from impacket import ImpactDecoder
from impacket import dhcp
import socket

dhcp_packet = (
    b'\x01'              # Message type: Boot Request (1 byte)
    b'\x01'              # Hardware type: Ethernet (1 byte)
    b'\x06'              # Hardware address length: 6 (1 byte)
    b'\x00'              # Hops: 0 (1 byte)
    b'\x39\x03\xF3\x26'  # Transaction ID: Random (4 bytes)
    b'\x00\x00'          # Seconds elapsed: 0 (2 bytes)
    b'\x80\x00'          # Flags: 0x8000 (Broadcast) (2 bytes)
    b'\x00\x00\x00\x00'  # Client IP address: 0.0.0.0 (4 bytes)
    b'\x00\x00\x00\x00'  # Your (client) IP address: 0.0.0.0 (4 bytes)
    b'\x00\x00\x00\x00'  # Next server IP address: 0.0.0.0 (4 bytes)
    b'\x00\x00\x00\x00'  # Relay agent IP address: 0.0.0.0 (4 bytes)
    b'\x00\x26\x9e\x04\x0a\x5b'  # Client MAC address (6 bytes)
    b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'  # Client hardware address padding (10 bytes)
    b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'  # Server name padding (64 bytes)
    b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'   # Boot filename padding (128 bytes)
    b'\x63\x82\x53\x63'  # Magic cookie: DHCP (4 bytes)
    # DHCP Options:
    b'\x35\x01\x01'
    b'\x32\x04\xc0\xa8\x01\x64'
    b'\x33\x04\x01\xa8\x01\x64'      # Option: (53) DHCP Message Type (Discover) (3 bytes)
    # b'\x3d\x07\x01\x00\x26\x9e\x04\x0a\x5b'  # Option: (61) Client identifier (7 bytes)
    b'\x37\x01\x03\x01\x06'  # Option: (55) Parameter Request List (5 bytes)
    # b'\xff'              # End Option (1 byte)
)

dhcp_decoder = ImpactDecoder.BootpDecoder()
dhcp_packet_decoded = dhcp_decoder.decode(dhcp_packet)
print(dhcp_packet_decoded)

Could anyone take a look at it?

@alexisbalbachan alexisbalbachan added bug Unexpected problem or unintended behavior and removed in review This issue or pull request is being analyzed labels Oct 17, 2024
@alexisbalbachan
Copy link
Contributor

As @emdete mentioned, this error can be solved by modifying the following condition to also include bytearray objects

if isinstance(data, bytes) and dataClassOrCode is b:

The fix may cause some unwanted splash damage so further testing is required.

Another option would be to fix the method responsible for calling structure.unpack with bytearray as an argument (instead of bytes). It was recently introduced by another PR: 3f64510.

We could convert options[...] to bytes in the following line:

value = self.unpack(format, options[i+2:i+2+size])

Both alternatives fix the problem

@alexisbalbachan alexisbalbachan linked a pull request Dec 5, 2024 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Unexpected problem or unintended behavior
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants