fortra/impacket

Intermittent unpacking errors during RPC communication

janedoe-lab opened this issue · 3 comments

Configuration

impacket version: v0.12.0.dev1+20231114.165227.4b56c18a
Python version: Python 3.11.6
Target OS: Windows 10 Pro

Debug Output With Command String

wmiexec.py -debug ./admin:password@127.0.0.1
Traceback (most recent call last):
  File "/home/user/.local/bin/wmiexec.py", line 93, in run
    iInterface = dcom.CoCreateInstanceEx(wmi.CLSID_WbemLevel1Login, wmi.IID_IWbemLevel1Login)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.local/pipx/venvs/impacket/lib/python3.11/site-packages/impacket/dcerpc/v5/dcomrt.py", line 1076, in CoCreateInstanceEx
    iInterface = scm.RemoteCreateInstance(clsid, iid)
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.local/pipx/venvs/impacket/lib/python3.11/site-packages/impacket/dcerpc/v5/dcomrt.py", line 1757, in RemoteCreateInstance
    self.__portmap.bind(IID_IRemoteSCMActivator)
  File "/home/user/.local/pipx/venvs/impacket/lib/python3.11/site-packages/impacket/dcerpc/v5/rpcrt.py", line 1041, in bind
    bindResp = MSRPCBindAck(resp.getData())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.local/pipx/venvs/impacket/lib/python3.11/site-packages/impacket/dcerpc/v5/rpcrt.py", line 750, in __init__
    MSRPCHeader.__init__(self,data,alignment)
  File "/home/user/.local/pipx/venvs/impacket/lib/python3.11/site-packages/impacket/dcerpc/v5/rpcrt.py", line 637, in __init__
    Structure.__init__(self,data, alignment)
  File "/home/user/.local/pipx/venvs/impacket/lib/python3.11/site-packages/impacket/structure.py", line 87, in __init__
    self.fromString(data)
  File "/home/user/.local/pipx/venvs/impacket/lib/python3.11/site-packages/impacket/dcerpc/v5/rpcrt.py", line 768, in fromString
    item = CtxItemResult(data)
           ^^^^^^^^^^^^^^^^^^^
  File "/home/user/.local/pipx/venvs/impacket/lib/python3.11/site-packages/impacket/structure.py", line 87, in __init__
    self.fromString(data)
  File "/home/user/.local/pipx/venvs/impacket/lib/python3.11/site-packages/impacket/structure.py", line 152, in fromString
    self[field[0]] = self.unpack(field[1], data[:size], dataClassOrCode = dataClassOrCode, field = field[0])
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.local/pipx/venvs/impacket/lib/python3.11/site-packages/impacket/structure.py", line 326, in unpack
    return self.unpack(two[0],data)
           ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/user/.local/pipx/venvs/impacket/lib/python3.11/site-packages/impacket/structure.py", line 385, in unpack
    return unpack(format, data)[0]
           ^^^^^^^^^^^^^^^^^^^^
struct.error: ('unpack requires a buffer of 20 bytes', 'When unpacking field \'TransferSyntax | 20s="" | b\'\\x04]\\x88\\x8a\\xeb\\x1c\\xc9\\x11\'[:20]\'')
[-] ('unpack requires a buffer of 20 bytes', 'When unpacking field \'TransferSyntax | 20s="" | b\'\\x04]\\x88\\x8a\\xeb\\x1c\\xc9\\x11\'[:20]\'')

Additional context

It happens without any rhyme or reason. Quite often it is enough to just restart it a few times to get it working. It happens only during RPC communication. SMB communication never throws anything like that. Also, TransferSyntax unpacking error is the most common, but sometimes it breaks earlier with other fields failing to decode.

I am not quite sure it is problem with Impacket, but so far I failed to find out the cause.

It happens with different VMs, different OSes.

Perhaps someone experienced similar errors, or maybe can give an idea how to debug it.

After some more digging, I found that adding sleep delay during binding before receiving the answer from the server "fixes" the problem - RPC related code starts working.

--- impacket/dcerpc/v5/rpcrt.old.py    
+++ impacket/dcerpc/v5/rpcrt.py   
@@ -22,6 +22,7 @@
 import logging
 import socket
 import sys
+import time
 from binascii import unhexlify
 from Cryptodome.Cipher import ARC4
 
@@ -1030,6 +1031,8 @@
 
         self._transport.send(packet.get_packet())
 
+        time.sleep(5)
+
         s = self._transport.recv()
 
         if s != 0:

This leads me to suspicion that it could be caused by one of two, or both, below:

  1. With VPN connection into client's networks, MTU on my network interface is significantly lower than standard 1500. I looked at Wireshark and do not see any large packets thos. But perhaps it might be involved somehow in the transit.

  2. Often link to the network has significant latency. Perhaps it plays a role, where server send two packets, but Impacket operates with assumption that all information will arrive in one packet.

quick question: this doesn't look like an issue for an specific impacket version right?

In general - yes, but I would expect different versions having slightly different communication and hence slightly different behavior here depending on version and networking setup.