Giter Club home page Giter Club logo

iec104's Introduction

IEC104

Protocol of IEC104 and IEC101

by chendajie 2014-2015

电网IEC104/IEC101通信协议

隔离协议内容与平台或者硬件相关性,已经在stm32平台和linux平台移植测试通过,可轻松移植到其他平台。

队列实现的隔离,目前实现简单的先入先出队列,可根据需求用其他队列算法替换。

移植调用实现:

1.在不同平台下,实现_iec10x结构体的函数指针(利用函数指针实现的接口)。

2.调用RegisterIEC10XMoudle,注册实现的_iec10x接口。

3.创建线程一调用Iex104_Receive管理收包解析。

4.创建线程二调用Iec10x_Scheduled实现出队调度。

5.创建线程三实现状态机Iec104_StateMachine,实现协议状态管理,协议包组包入队。

代码内容

IEC0x目录

iec101.c   iec101协议包内容

iec104.c   iec104协议包内容

iec10x.c   队列初始化,入队出对实现,队列优先级等相关实现,队列调度实现

PRIO_QUEUE_Iec10x.c   队列具体算法实现

test目录

linux上简单测试代码,仅供参考,作者具体协议应用在stm32上,利用状态机控制数据包入队与出队调度

重要函数:

Iec10x_Scheduled:出队调度

IEC10X_Enqueue:入队函数

IEC10X_Dequeue:出队函数

IEC10X_FindQHead:查找最高优先级数据包

IEC10X_XXX:前缀为IEC10X_的函数为各个协议包的组包函数

Iec104_StateMachine: 104协议状态机

Iex104_Receive:收包解析

RegisterIEC10XMoudle:协议模块注册,初始化

重要结构体:

用函数指针实现的移植接口,根据不同平台与硬件特性,选择性实现以下接口

typedef struct _iec10x {

    char * name;
    int (* Init)(void);
    void (* Delay_ms)(uint16_t);
    void (* CloseLink)(void);
    void *(* Malloc)(uint8_t NumByte);
    void (* Free)(void *buffer);
    uint8_t (* enqueue)(Iec10x_PrioQueue_T *QueueHdr, Iec10x_PrioNode_T *NewNode);
    Iec10x_PrioNode_T *(* dequeue)(Iec10x_PrioQueue_T * QueueHdr);
    Iec10x_PrioNode_T *(* FindQHead)(Iec10x_PrioQueue_T * QueueHdr);
    char (* GetPrio)(void);
    void (* InitQueue)(Iec10x_PrioQueue_T *PrioQueue);
    void (* ClearQueue)(Iec10x_PrioQueue_T * QueueHdr);
    uint8_t (* Send)(int socketfd,char *data,int len);
    uint32_t (* SetTime)(PCP56Time2a_T time);
    uint32_t (* GetTime)(PCP56Time2a_T time);
    int8_t (* GetStationState)(uint16_t Addr, uint8_t DevType);
    float (* GetStaValue)(uint16_t Addr, uint8_t DevType);
    uint16_t (* GetLinkAddr)(void);
    int8_t (* GetInfoNum)(uint8_t *InfoNum, uint8_t DevType);
    int8_t (* SetConfig)(long Value, uint32_t addr);
    int8_t (* SaveFirmware)(uint8_t FirmLen, uint8_t *buf,uint32_t FirmwareType, uint32_t Iec10x_Update_SeekAddr);
    int8_t (* CheckFirmware)(uint32_t FirmwareType, uint32_t TotalLen);
    int8_t (* UpdateFirmware)(uint32_t FirmwareType);
    int8_t (* BackoffFirmware)(uint32_t FirmwareType);

#ifdef IEC10XLOCK
    void (* LOCK)(void);
    void (* UNLOCK)(void);
#endif

} *PIEC10X_T, IEC10X_T;

iec104's People

Contributors

airpig2011 avatar grandnew avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

iec104's Issues

SEGV found in function Iec104_Deal_FirmUpdate

I used gcc 5.4.0 with CFLAGS=-g -fsanitize=address CXXFLAGS=-g -fsanitize=address LDFLAGS=-fsanitize=address to compile the IEC104, and use LD_PRELOAD=/root/preeny/x86_64-linux-gnu/desock.so ./iec104_monitor -m server -n 1 < test_case to run the program, while I found a SEGV in IEC10X/Iec104.c function Iec104_Deal_FirmUpdate .

here is the code:

 if(CsumTemp == csum){
                    LOG("-%s-,data need ack:%d,Len:%d,seek:%d \n",__FUNCTION__,FlagNum,DataLen,Iec10x_Update_SeekAddr);
                    
                    for(i=0; i<3; i++){
                        ret = IEC10X->SaveFirmware(DataLen,DataPtr,FirmwareType,Iec10x_Update_SeekAddr);
                        if(ret == RET_SUCESS)
                            break;
                    }
                    
                    if(ret == RET_ERROR){
                        LOG("save firmware error \n");
                        break;
                    }
                    Iec104_BuildDataAck(TI, IEC10X_COT_DATA_ACK, FirmwareType, FlagNum,1);
                    
                    FirmFlagCount = FlagNum;
                    Iec10x_Update_SeekAddr+=DataLen;
                }

seems that you do not check the scenario where the datalen gets 0, while it actually have data, as well as the scenario where it FirmType becomes unexpected value.

the ASAN output

 ver -n 1 < crash1/crash_input_3

Register "Linux" IEC104 Success, < HuiXing 2014-2015 > ...
mode :(0), port: (0), ip: (), station num: (1)
Iec104 Server Mode
Iec104 Socket Ok(10000) !
Iec104 Bind Ok(10000) !
Iec104 Listen Ok(10000)
feilong:Iec104 Listen Ok(10000)
feilong:Waiting for connection
Accept ok!
Server start get connect from 0 : 0x2328
#####################received
[DumpHEX]Length:873
68:00:68:00:68:00:68:0f    68:00:00:00:6e:21:00:68
00:00:68:7f:00:68:00:68    01:13:68:0f:68:00:68:00
80:01:0e:10:00:00:00:68    00:48:00:68:0f:68:00:68
00:80:00:00:68:00:00:00    70:68:01:70:68:0f:68:00
68:00:6e:21:00:68:00:00    68:68:00:68:00:68:01:13
68:0f:68:00:68:00:80:01    0e:10:00:68:00:68:00:68
00:68:0f:68:00:00:00:02    00:00:68:00:00:00:70:68
01:4e:68:0f:68:00:68:00    6e:21:00:68:00:00:68:7f
00:68:00:68:01:13:68:0f    68:00:68:00:80:01:0e:10
00:00:00:68:00:48:00:68    0f:68:00:68:00:80:00:00
68:00:00:00:70:68:01:70    68:0f:68:00:68:00:6e:21
00:68:00:00:68:68:00:68    00:68:01:13:68:0f:68:00
68:00:80:01:0e:10:00:00    00:68:00:48:00:68:0f:68
00:82:00:80:01:0e:10:00    00:00:68:00:01:00:68:0f
68:00:82:00:80:01:ff:00    00:00:00:68:00:48:00:68
0f:68:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:11:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:48    48:48:48:48:48:48:48:48
48:48:48:48:48:48:48:ff    ff:26:80:01:0e:10:00:00
68:68:00:48:00:68:0f:68    ff:ff:26:80:01:0e:10:00
00:68:00:48:00:0e:10:00    00
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,0)
-Iec104_Deal_I-, error Type(104)
-Iex104_Receive-,Frame Type I
-Iec104_Deal_I-, error asdu addr(0)(216e)
-Iex104_Receive-,Frame Type I
-Iec104_Deal_I-, error asdu addr(0)(6800)
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,0), Send(0,53)
-Iec104_Deal_SN-, error,send last(52),now(52). recv last(52),now(0)
-Iex104_Receive-,Frame Type U
>Iec104_Deal_U<, function STOPDT
IEC10X_Enqueue,Prio(0) elementNum(0)len(6)(6)
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,53)
++++Asdu Type Firmware Update...
update flag error! need:1,flag:72
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,53)
++++Asdu Type Firmware Update...
-Iec104_Deal_FirmUpdate-,data:28673,Len:17 error cot:
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,53)
-Iec104_Deal_I-, error Type(110)
-Iex104_Receive-,Frame Type U
>Iec104_Deal_U<, function STOPDT
IEC10X_Enqueue,Prio(0) elementNum(1)len(6)(6)
-Iex104_Receive-,Frame Type I
-Iec104_Deal_I-, error asdu addr(0)(6800)
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,0), Send(0,53)
-Iec104_Deal_SN-, error,send last(52),now(52). recv last(52),now(0)
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,53)
-Iec104_Deal_I-, error Type(110)
-Iex104_Receive-,Frame Type U
>Iec104_Deal_U<, function STOPDT
IEC10X_Enqueue,Prio(0) elementNum(2)len(6)(6)
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,53)
++++Asdu Type Firmware Update...
update flag error! need:1,flag:72
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,53)
++++Asdu Type Firmware Update...
-Iec104_Deal_FirmUpdate-,data:28673,Len:17 error cot:
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,53)
-Iec104_Deal_I-, error Type(110)
-Iex104_Receive-,Frame Type U
>Iec104_Deal_U<, function STOPDT
IEC10X_Enqueue,Prio(0) elementNum(3)len(6)(6)
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,53)
++++Asdu Type Firmware Update...
update flag error! need:1,flag:72
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,65), Send(0,53)
++++Asdu Type Firmware Update...
-Iec104_Deal_FirmUpdate-,data need ack:1,Len:255,seek:0 
ASAN:SIGSEGV
=================================================================
==16344==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000000000 bp 0x7ffef3331d50 sp 0x7ffef3331c48 T0)         ==16344==Hint: pc points to the zero page.

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 ??
==16344==ABORTING

stack-buffer-overflow in Iex104_Receive

Hi, all. As I mentioned in #9, the project should be fixed.
Then I find that this file can crash the program.
I used Clang 6.0 and AddressSanitizer(CFLAGS+="-g -fsanitize=address" in Makefile) to compile the program. In addtion, I run the program with the help of preeny(Channels socket communication to the console) by the following command:

LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.2:~/Polar/preeny/x86_64-linux-gnu/desock.so ./iec104_monitor -m server < $crash

Here is ASAN information:

=================================================================
==23912==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fe592dfee6c at pc 0x00000040967c bp 0x7fe592dfe6c0 sp 0x7fe592dfe6b0
READ of size 1 at 0x7fe592dfee6c thread T1
    #0 0x40967b in Iex104_Receive ..//IEC10X/Iec104.c:1297
    #1 0x40b661 in Iec104_main /home/fouzhe/IEC104/test/main.c:140
    #2 0x7fe595f666b9 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76b9)
    #3 0x7fe595c9c41c in clone (/lib/x86_64-linux-gnu/libc.so.6+0x10741c)

Address 0x7fe592dfee6c is located in stack of thread T1 at offset 1852 in frame
    #0 0x40b12a in Iec104_main /home/fouzhe/IEC104/test/main.c:73

  This frame has 6 object(s):
    [32, 36) 'sin_size'
    [96, 100) 'on'
    [160, 168) 'tid1'
    [224, 240) 's_add'
    [288, 304) 'c_add'
    [352, 1852) 'Iec104_RecvBuf' <== Memory access at offset 1852 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
Thread T1 created by T0 here:
    #0 0x7fe5963d6253 in pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x36253)
    #1 0x40c190 in main /home/fouzhe/IEC104/test/main.c:301
    #2 0x7fe595bb582f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

SUMMARY: AddressSanitizer: stack-buffer-overflow ..//IEC10X/Iec104.c:1297 Iex104_Receive
Shadow bytes around the buggy address:
  0x0ffd325b7d70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ffd325b7d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ffd325b7d90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ffd325b7da0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ffd325b7db0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0ffd325b7dc0: 00 00 00 00 00 00 00 00 00 00 00 00 00[04]f3 f3
  0x0ffd325b7dd0: f3 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00
  0x0ffd325b7de0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ffd325b7df0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ffd325b7e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0ffd325b7e10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
==23912==ABORTING

New SEGV in function Iec104_Deal_FirmUpdate which is different from issue#5 and issue#6

Hello. I built protocol IEC104 on my ubuntu16.04 machine with AddressSanitizer(export CFLAGS="-g -fsanitize=address" CXXFLAGS="-g -fsanitize=address" LDFLAGS="-fsanitize=address" before make) .

And I use prenny desock tool to build channels socket communication to the console.

But when I use the following data ( here in hexadecimal format for easy understanding but must be inputted as binary format file ) as the input to the server TCP socket 10000, there will be a SEGV during the running which is different from issue#5 and issue#6 .

68:00:68:00:68:00:68:0f 68:00:00:00:02:00:00:68 00:00:00:70:68:01:4e:68 0f:68:00:68:00:6e:21:00 68:00:00:68:7f:00:68:00 68:01:13:68:0f:68:00:68 00:80:01:0e:10:00:00:00 68:00:48:00:68:0f:68:00 68:00:80:00:00:68:00:00 00:70:68:01:70:68:0f:68 00:68:00:6e:21:00:68:00 00:68:68:00:68:00:68:01 13:68:0f:68:00:68:00:80 01:0e:10:00:68:00:68:00 68:00:68:0f:68:00:00:00 02:00:00:68:00:00:00:70 68:01:4e:68:0f:68:00:68 00:6e:21:00:68:00:00:68 7f:00:68:00:68:01:13:68 0f:68:00:68:00:80:01:0e 10:00:00:00:68:00:48:00 68:0f:83:00:68:00:80:00 00:68:00:00:00:70:68:01 70:68:0f:68:00:68:00:6e 21:00:68:00:00:68:68:00 68:00:68:01:13:68:0f:68 00:68:00:80:01:0e:10:00 00:00:68:00:48:00:68:10 68:00:82:00:80:01:0e:00 00:00:00:68:00:01:00:00 ff:68:00:82:00:80:01:ff 00:00:00:00:68:00:48:00 0e:10:00:00

The way I built iec104_monitor is as you sad here, just cut the main function to the bottom in ./test/main.c and change the route of source files in ./test/Makefile.

The command line is as follows:
LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libasan.so.2:/root/preeny/x86_64-linux-gnu/desock.so" ./iec104_monitor -m server -n 1 < ./test_input
where
/usr/lib/x86_64-linux-gnu/libasan.so.2 is the lib of asan,
/root/preeny/x86_64-linux-gnu/desock.so is the lib of preeny desock
./test_input is the binaray format file which contains the test input as mentioned just now in hexadecimal format.

The runtime error information is similar as issue#5 and issue#6.
But the gdb debug information is not similar in the crash position and I think they get different crashes in the source code.

The runtime error information:

Register "Linux" IEC104 Success, < HuiXing 2014-2015 > ...
mode :(0), port: (0), ip: (), station num: (1) 
Iec104 Server Mode 
Iec104 Socket Ok(10000) !
Iec104 Bind Ok(10000) !
Iec104 Listen Ok(10000)
feilong:Iec104 Listen Ok(10000)
feilong:Waiting for connection
Accept ok!
Server start get connect from 0 : 0x2328
#####################received 
[DumpHEX]Length:260 
68:00:68:00:68:00:68:0f    68:00:00:00:02:00:00:68
00:00:00:70:68:01:4e:68    0f:68:00:68:00:6e:21:00
68:00:00:68:7f:00:68:00    68:01:13:68:0f:68:00:68
00:80:01:0e:10:00:00:00    68:00:48:00:68:0f:68:00
68:00:80:00:00:68:00:00    00:70:68:01:70:68:0f:68
00:68:00:6e:21:00:68:00    00:68:68:00:68:00:68:01
13:68:0f:68:00:68:00:80    01:0e:10:00:68:00:68:00
68:00:68:0f:68:00:00:00    02:00:00:68:00:00:00:70
68:01:4e:68:0f:68:00:68    00:6e:21:00:68:00:00:68
7f:00:68:00:68:01:13:68    0f:68:00:68:00:80:01:0e
10:00:00:00:68:00:48:00    68:0f:83:00:68:00:80:00
00:68:00:00:00:70:68:01    70:68:0f:68:00:68:00:6e
21:00:68:00:00:68:68:00    68:00:68:01:13:68:0f:68
00:68:00:80:01:0e:10:00    00:00:68:00:48:00:68:10
68:00:82:00:80:01:0e:00    00:00:00:68:00:01:00:00
ff:68:00:82:00:80:01:ff    00:00:00:00:68:00:48:00
0e:10:00:00
-Iex104_Receive-,Frame Type I 
Receive Pakage I(52,52), Send(0,0)
-Iec104_Deal_I-, error Type(104) 
-Iex104_Receive-,Frame Type I 
-Iec104_Deal_I-, error asdu addr(0)(2) 
-Iex104_Receive-,Frame Type I 
-Iec104_Deal_I-, error asdu addr(0)(6800) 
-Iex104_Receive-,Frame Type I 
Receive Pakage I(52,0), Send(0,53)
-Iec104_Deal_SN-, error,send last(52),now(52). recv last(52),now(0) 
-Iex104_Receive-,Frame Type I 
Receive Pakage I(52,52), Send(0,53)
-Iec104_Deal_I-, error Type(110) 
-Iex104_Receive-,Frame Type U 
>Iec104_Deal_U<, function STOPDT 
IEC10X_Enqueue,Prio(0) elementNum(0)len(6)(6) 
-Iex104_Receive-,Frame Type I 
Receive Pakage I(52,52), Send(0,53)
++++Asdu Type Firmware Update... 
update flag error! need:1,flag:72
-Iex104_Receive-,Frame Type I 
Receive Pakage I(52,52), Send(0,53)
++++Asdu Type Firmware Update... 
-Iec104_Deal_FirmUpdate-,data:28673,Len:17 error cot: 
-Iex104_Receive-,Frame Type I 
Receive Pakage I(52,52), Send(0,53)
-Iec104_Deal_I-, error Type(110) 
-Iex104_Receive-,Frame Type U 
>Iec104_Deal_U<, function STOPDT 
IEC10X_Enqueue,Prio(0) elementNum(1)len(6)(6) 
-Iex104_Receive-,Frame Type I 
-Iec104_Deal_I-, error asdu addr(0)(6800) 
-Iex104_Receive-,Frame Type I 
Receive Pakage I(52,0), Send(0,53)
-Iec104_Deal_SN-, error,send last(52),now(52). recv last(52),now(0) 
-Iex104_Receive-,Frame Type I 
Receive Pakage I(52,52), Send(0,53)
-Iec104_Deal_I-, error Type(110) 
-Iex104_Receive-,Frame Type U 
>Iec104_Deal_U<, function STOPDT 
IEC10X_Enqueue,Prio(0) elementNum(2)len(6)(6) 
-Iex104_Receive-,Frame Type I 
Receive Pakage I(52,52), Send(0,53)
++++Asdu Type Firmware Update... 
update flag error! need:1,flag:72
-Iex104_Receive-,Frame Type U 
>Iec104_Deal_U<, function TESTER ACK
-Iex104_Receive-,Frame Type I 
Receive Pakage I(52,52), Send(0,53)
-Iec104_Deal_I-, error Type(110) 
-Iex104_Receive-,Frame Type U 
>Iec104_Deal_U<, function STOPDT 
IEC10X_Enqueue,Prio(0) elementNum(3)len(6)(6) 
-Iex104_Receive-,Frame Type I 
Receive Pakage I(52,52), Send(0,53)
++++Asdu Type Firmware Update... 
update flag error! need:1,flag:72
-Iex104_Receive-,Frame Type I 
Receive Pakage I(52,65), Send(0,53)
++++Asdu Type Firmware Update... 
-Iec104_Deal_FirmUpdate-,data:1,Len:0,seek:0 
ASAN:SIGSEGV
=================================================================
==21865==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000000000 bp 0x7ffcd2c02ae0 sp 0x7ffcd2c028c8 T0)
==21865==Hint: pc points to the zero page.

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 ??
==21865==ABORTING

I use gdb to debug it and the information is as following:

Thread 2 "iec104_monitor" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff37ff700 (LWP 21270)]
0x0000000000000000 in ?? ()
(gdb) backtrace
#0  0x0000000000000000 in ?? ()
#1  0x000000000040975b in Iec104_Deal_FirmUpdate (asdu=asdu@entry=0x7ffff37fe964, Len=Len@entry=18 '\022') at ../IEC10X/Iec104.c:1066
#2  0x000000000040a631 in Iec104_Deal_I (Iec104Data=Iec104Data@entry=0x7ffff37fe95e, len=len@entry=18) at ../IEC10X/Iec104.c:1208
#3  0x000000000040adac in Iex104_Receive (buf=buf@entry=0x7ffff37fe880 "h", len=len@entry=260) at ../IEC10X/Iec104.c:1305
#4  0x000000000040fe67 in Iec104_main (arg=<optimized out>) at main.c:138
#5  0x00007ffff6a306ba in start_thread (arg=0x7ffff37ff700) at pthread_create.c:333
#6  0x00007ffff676641d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
(gdb) 
#0  0x0000000000000000 in ?? ()
#1  0x000000000040975b in Iec104_Deal_FirmUpdate (asdu=asdu@entry=0x7ffff37fe964, Len=Len@entry=18 '\022') at ../IEC10X/Iec104.c:1066
#2  0x000000000040a631 in Iec104_Deal_I (Iec104Data=Iec104Data@entry=0x7ffff37fe95e, len=len@entry=18) at ../IEC10X/Iec104.c:1208
#3  0x000000000040adac in Iex104_Receive (buf=buf@entry=0x7ffff37fe880 "h", len=len@entry=260) at ../IEC10X/Iec104.c:1305
#4  0x000000000040fe67 in Iec104_main (arg=<optimized out>) at main.c:138
#5  0x00007ffff6a306ba in start_thread (arg=0x7ffff37ff700) at pthread_create.c:333
#6  0x00007ffff676641d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
(gdb) 

           

SEGV in function Iec104_Deal_FirmUpdate which is different from issue#5

Hello. I built protocol IEC104 on my ubuntu16.04 machine with AddressSanitizer(export CFLAGS="-g -fsanitize=address" CXXFLAGS="-g -fsanitize=address" LDFLAGS="-fsanitize=address" before make) .

And I use prenny desock tool to build channels socket communication to the console.

But when I use the following data ( here in hexadecimal format for easy understanding but must be inputted as binary format file ) as the input to the server TCP socket 10000, there will be a SEGV during the running which is different from issue#5 .

68:00:68:00:68:00:68:0f 68:00:00:00:6e:21:00:68 00:00:68:7f:00:68:00:68 01:13:68:0f:68:00:68:00 80:01:0e:10:00:00:00:68 00:48:00:68:0f:68:00:68 00:80:00:00:68:00:00:00 70:68:01:70:68:0f:68:00 68:00:6e:21:00:68:00:00 68:68:00:68:00:68:01:13 68:0f:68:00:68:00:80:01 0e:10:00:68:00:68:00:68 00:68:0f:68:00:00:00:02 00:00:68:00:00:00:70:68 01:4e:68:0f:68:00:68:00 6e:21:00:68:00:00:68:7f 00:68:00:68:01:13:68:0f 68:00:68:00:80:01:0e:10 00:00:00:68:00:48:00:68 0f:68:00:68:00:80:00:00 68:00:00:00:70:68:01:70 68:0f:68:00:68:00:6e:21 00:68:00:00:68:68:00:68 00:68:01:13:68:0f:68:00 68:00:80:01:0e:10:00:00 00:68:00:48:00:68:0f:68 00:82:00:80:01:0e:10:00 00:00:68:00:01:00:68:0f 68:00:82:00:80:01:ff:00 00:00:00:68:00:48:00:68 0f:68:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:11:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:48 48:48:48:48:48:48:48:ff ff:26:80:01:0e:10:00:00 68:68:00:48:00:68:0f:68 ff:ff:26:80:01:0e:10:00 00:68:00:48:00:0e:10:00 00

The way I built iec104_monitor is as you sad here, just cut the main function to the bottom in ./test/main.c and change the route of source files in ./test/Makefile.

The command line is as follows:
LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libasan.so.2:/root/preeny/x86_64-linux-gnu/desock.so" ./iec104_monitor -m server -n 1 < ./test_input
where
/usr/lib/x86_64-linux-gnu/libasan.so.2 is the lib of asan,
/root/preeny/x86_64-linux-gnu/desock.so is the lib of preeny desock
./test_input is the binary format file which contains the test input as mentioned above in hexadecimal format for easy understanding.

The runtime error information is similar as issue#5.
But the gdb debug information is not similar and I think they get crash in different position.

I use gdb to debug it and the information is as following:

Thread 2 "iec104_monitor" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff37ff700 (LWP 7241)]
0x0000000000000000 in ?? ()
(gdb) backtrace
#0  0x0000000000000000 in ?? ()
#1  0x0000000000409858 in Iec104_Deal_FirmUpdate (asdu=asdu@entry=0x7ffff37fe953, Len=Len@entry=17 '\021') at ../IEC10X/Iec104.c:1100
#2  0x000000000040a631 in Iec104_Deal_I (Iec104Data=Iec104Data@entry=0x7ffff37fe94d, len=len@entry=17) at ../IEC10X/Iec104.c:1208
#3  0x000000000040adac in Iex104_Receive (buf=buf@entry=0x7ffff37fe880 "h", len=len@entry=873) at ../IEC10X/Iec104.c:1305
#4  0x000000000040fe67 in Iec104_main (arg=<optimized out>) at main.c:138
#5  0x00007ffff6a306ba in start_thread (arg=0x7ffff37ff700) at pthread_create.c:333
#6  0x00007ffff676641d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
(gdb) 
#0  0x0000000000000000 in ?? ()
#1  0x0000000000409858 in Iec104_Deal_FirmUpdate (asdu=asdu@entry=0x7ffff37fe953, Len=Len@entry=17 '\021') at ../IEC10X/Iec104.c:1100
#2  0x000000000040a631 in Iec104_Deal_I (Iec104Data=Iec104Data@entry=0x7ffff37fe94d, len=len@entry=17) at ../IEC10X/Iec104.c:1208
#3  0x000000000040adac in Iex104_Receive (buf=buf@entry=0x7ffff37fe880 "h", len=len@entry=873) at ../IEC10X/Iec104.c:1305
#4  0x000000000040fe67 in Iec104_main (arg=<optimized out>) at main.c:138
#5  0x00007ffff6a306ba in start_thread (arg=0x7ffff37ff700) at pthread_create.c:333
#6  0x00007ffff676641d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
(gdb) 
           

A SEGV bug in function Iec104_Deal_I

Hello. I built this protocol IEC104 on my ubuntu16.04 machine.
The command line to build the project is:
Use GCC to build:
cd ./test && make

And I use prenny desock tool to redirect TCP socket communication to the console. I save the preeny source code in the initial project and the project which includes preeny can by found at this address.
The command to build preeny is :
cd ./preeny && make

But when I use the following file as the input file to test the iec104_monitor on the server mode. The monitor will result in crash. This file can be found at this address.

The command line is as following:
LD_PRELOAD=./preeny/x86_64-linux-gnu/desock.so ./test/iec104_monitor -m server -n 1 < ./crash/crash_input_1
where ./preeny/x86_64-linux-gnu/desock.so is the library of preeny desock.

So the commands to touch the crash from the very beginning is:

git clone https://github.com/NiceJob171/IEC104.git
cd ./IEC104
cd ./test  && make
cd ..
cd ./preeny && make
cd ..
LD_PRELOAD=./preeny/x86_64-linux-gnu/desock.so ./test/iec104_monitor -m server -n 1 < ./crash/crash_input_1

This crash is a SEGV crash in fucntion Iec104_Deal_I and the crash line is at ../IEC10X/Iec104.c:1214.

I use gdb to debug it and the crash information is as following:

[DumpHEX]Length:6 
68:04:43:00:02:21
Send Ok!
hC!IEC10X_Enqueue,Prio(0) elementNum(0)len(6)(6) 
Tester Count(2)... 
Thread 2 "iec104_monitor" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff37ff700 (LWP 42308)]
0x0000000000000000 in ?? ()
(gdb) backtrace
#0  0x0000000000000000 in ?? ()
#1  0x000000000040a605 in Iec104_Deal_I (Iec104Data=Iec104Data@entry=0x7ffff37fe880, len=len@entry=137) at ../IEC10X/Iec104.c:1214
#2  0x000000000040adac in Iex104_Receive (buf=buf@entry=0x7ffff37fe880 "h\207", len=len@entry=8) at ../IEC10X/Iec104.c:1305
#3  0x000000000040fe67 in Iec104_main (arg=<optimized out>) at main.c:138
#4  0x00007ffff6a306ba in start_thread (arg=0x7ffff37ff700) at pthread_create.c:333
#5  0x00007ffff676641d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109

联系作者

想联系一下作者,有偿咨询,18001166985(微信同手机号)!

A SEGV vulnerability in function Iec104_Deal_FirmUpdate

Hello. I built this protocol IEC104 on my ubuntu16.04 machine.
The command line to build the project is:
Use GCC to build:
cd ./test && make

And I use prenny desock tool to redirect TCP socket communication to the console. I save the preeny source code in the initial project and the project which includes preeny can by found at this address.
The command to build preeny is :
cd ./preeny && make

But when I use the following file as the input file to test the iec104_monitor on the server mode. The monitor will result in crash. This file can be found at this address.

The command line is as following:
LD_PRELOAD=./preeny/x86_64-linux-gnu/desock.so ./test/iec104_monitor -m server -n 1 < ./crash/crash_input_2
where ./preeny/x86_64-linux-gnu/desock.so is the library of preeny desock.

So the commands to touch the crash from the very beginning is:

git clone https://github.com/NiceJob171/IEC104.git
cd ./IEC104
cd ./test  && make
cd ..
cd ./preeny && make
cd ..
LD_PRELOAD=./preeny/x86_64-linux-gnu/desock.so ./test/iec104_monitor -m server -n 1 < ./crash/crash_input_2

This crash is a SEGV crash in fucntion Iec104_Deal_FirmUpdate and the crash line is at ./IEC10X/Iec104.c:1129.

I use gdb to debug it and the crash information is as following:

Thread 2 "iec104_monitor" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff37ff700 (LWP 19690)]
0x0000000000000000 in ?? ()
(gdb) backtrace
#0  0x0000000000000000 in ?? ()
#1  0x000000000040898d in Iec104_Deal_FirmUpdate (asdu=asdu@entry=0x7ffff37fe886, Len=Len@entry=226 '\342') at ../IEC10X/Iec104.c:1129
#2  0x000000000040a631 in Iec104_Deal_I (Iec104Data=Iec104Data@entry=0x7ffff37fe880, len=len@entry=226) at ../IEC10X/Iec104.c:1208
#3  0x000000000040adac in Iex104_Receive (buf=buf@entry=0x7ffff37fe880 "h\340@", len=len@entry=43) at ../IEC10X/Iec104.c:1305
#4  0x000000000040fe67 in Iec104_main (arg=<optimized out>) at main.c:138
#5  0x00007ffff6a306ba in start_thread (arg=0x7ffff37ff700) at pthread_create.c:333
#6  0x00007ffff676641d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
(gdb) 
#0  0x0000000000000000 in ?? ()
#1  0x000000000040898d in Iec104_Deal_FirmUpdate (asdu=asdu@entry=0x7ffff37fe886, Len=Len@entry=226 '\342') at ../IEC10X/Iec104.c:1129
#2  0x000000000040a631 in Iec104_Deal_I (Iec104Data=Iec104Data@entry=0x7ffff37fe880, len=len@entry=226) at ../IEC10X/Iec104.c:1208
#3  0x000000000040adac in Iex104_Receive (buf=buf@entry=0x7ffff37fe880 "h\340@", len=len@entry=43) at ../IEC10X/Iec104.c:1305
#4  0x000000000040fe67 in Iec104_main (arg=<optimized out>) at main.c:138
#5  0x00007ffff6a306ba in start_thread (arg=0x7ffff37ff700) at pthread_create.c:333
#6  0x00007ffff676641d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
(gdb) 

SEGV in function Iec104_Deal_I

Hello. I built protocol IEC104 on my ubuntu16.04 machine with AddressSanitizer(export CFLAGS="-g -fsanitize=address" CXXFLAGS="-g -fsanitize=address" LDFLAGS="-fsanitize=address" before make) .
And I use prenny desock tool to build channels socket communication to the console.

But when I use the following data ( here in hexadecimal format for easy understanding but must be inputted as binary format file ) as the input to the server TCP socket 10000, there will be a SEGV during the running.
68:87:00:21:87:00:81:00

The way I built iec104_monitor is as you sad here, just cut the main function to the bottom in ./test/main.c and change the route of source files in ./test/Makefile.

The command line is as follows:
LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libasan.so.2:/root/preeny/x86_64-linux-gnu/desock.so" ./iec104_monitor -m server -n 1 < ./test_input
where
/usr/lib/x86_64-linux-gnu/libasan.so.2 is the lib of asan,
/root/preeny/x86_64-linux-gnu/desock.so is the lib of preeny desock
./test_input is the binary format file which contains the test input as mentioned above in hexadecimal format for easy understanding.

The runtime error information is:

Register "Linux" IEC104 Success, < HuiXing 2014-2015 > ...
mode :(0), port: (0), ip: (), station num: (1) 
Iec104 Server Mode 
Iec104 Socket Ok(10000) !
Iec104 Bind Ok(10000) !
Iec104 Listen Ok(10000)
Accept ok!
Server start get connect from 0 : 0x2328
#####################received 
[DumpHEX]Length:8 
68:87:00:21:87:00:81:00
-Iex104_Receive-,Frame Type I 
Receive Pakage I(4224,67), Send(0,0)
++++Asdu Type Firmware Backoff... 
IEC10X_Enqueue,Prio(1) elementNum(0)len(17)(17) 
ASAN:SIGSEGV
=================================================================
==11061==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000000000 bp 0x7f46d8dfe610 sp 0x7f46d8dfe5e8 T1)
==11061==Hint: pc points to the zero page.

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 ??
Thread T1 created by T0 here:
    #0 0x7f46dc3c0253 in pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x36253)
    #1 0x4020a9 in main /root/feilong/libiec104_fuzz/asan-mode/IEC10X/main.c:299

==11061==ABORTING

I use gdb to debug it and the information is as following:

[DumpHEX]Length:6 
68:04:43:00:02:21
Send Ok!
hC!IEC10X_Enqueue,Prio(0) elementNum(0)len(6)(6) 
Tester Count(2)... 
Thread 2 "iec104_monitor" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff37ff700 (LWP 42308)]
0x0000000000000000 in ?? ()
(gdb) backtrace
#0  0x0000000000000000 in ?? ()
#1  0x000000000040a605 in Iec104_Deal_I (Iec104Data=Iec104Data@entry=0x7ffff37fe880, len=len@entry=137) at ../IEC10X/Iec104.c:1214
#2  0x000000000040adac in Iex104_Receive (buf=buf@entry=0x7ffff37fe880 "h\207", len=len@entry=8) at ../IEC10X/Iec104.c:1305
#3  0x000000000040fe67 in Iec104_main (arg=<optimized out>) at main.c:138
#4  0x00007ffff6a306ba in start_thread (arg=0x7ffff37ff700) at pthread_create.c:333
#5  0x00007ffff676641d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109

SEGV in function Iec104_Deal_FirmUpdate

I used gcc 5.4.0 with CFLAGS=-g -fsanitize=address CXXFLAGS=-g -fsanitize=address LDFLAGS=-fsanitize=address to compile the IEC104, and use LD_PRELOAD=/root/preeny/x86_64-linux-gnu/desock.so ./iec104_monitor -m server -n 1 < test_case to run the program, while I found a SEGV in IEC10X/Iec104.c function Iec104_Deal_FirmUpdate.

here is the code:

if(CsumTemp == csum){
                    LOG("-%s-,data:%d,Len:%d,seek:%d \n",__FUNCTION__,FlagNum,DataLen,Iec10x_Update_SeekAddr);
                    for(i=0; i<3; i++){
                        ret = IEC10X->SaveFirmware(DataLen,DataPtr,FirmwareType, Iec10x_Update_SeekAddr);
                        if(ret == RET_SUCESS)
                            break;
                    }
                    if(ret == RET_ERROR){
                        LOG("save firmware error \n");
                        break;
                    }

                    FirmFlagCount = FlagNum;
                    Iec10x_Update_SeekAddr+=DataLen;
                }

seems that you do not check the situation where DataLen and FirmwareType become unexpected, which causes the program to exit unexpectedly.

the ASAN output

Register "Linux" IEC104 Success, < HuiXing 2014-2015 > ...
mode :(0), port: (0), ip: (), station num: (1)
Iec104 Server Mode
Iec104 Socket Ok(10000) !
Iec104 Bind Ok(10000) !
Iec104 Listen Ok(10000)
feilong:Iec104 Listen Ok(10000)
feilong:Waiting for connection
Accept ok!
Server start get connect from 0 : 0x2328
#####################received
[DumpHEX]Length:260
68:00:68:00:68:00:68:0f    68:00:00:00:02:00:00:68
00:00:00:70:68:01:4e:68    0f:68:00:68:00:6e:21:00
68:00:00:68:7f:00:68:00    68:01:13:68:0f:68:00:68
00:80:01:0e:10:00:00:00    68:00:48:00:68:0f:68:00
68:00:80:00:00:68:00:00    00:70:68:01:70:68:0f:68
00:68:00:6e:21:00:68:00    00:68:68:00:68:00:68:01
13:68:0f:68:00:68:00:80    01:0e:10:00:68:00:68:00
68:00:68:0f:68:00:00:00    02:00:00:68:00:00:00:70
68:01:4e:68:0f:68:00:68    00:6e:21:00:68:00:00:68
7f:00:68:00:68:01:13:68    0f:68:00:68:00:80:01:0e
10:00:00:00:68:00:48:00    68:0f:83:00:68:00:80:00
00:68:00:00:00:70:68:01    70:68:0f:68:00:68:00:6e
21:00:68:00:00:68:68:00    68:00:68:01:13:68:0f:68
00:68:00:80:01:0e:10:00    00:00:68:00:48:00:68:10
68:00:82:00:80:01:0e:00    00:00:00:68:00:01:00:00
ff:68:00:82:00:80:01:ff    00:00:00:00:68:00:48:00
0e:10:00:00
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,0)
-Iec104_Deal_I-, error Type(104)
-Iex104_Receive-,Frame Type I
-Iec104_Deal_I-, error asdu addr(0)(2)
-Iex104_Receive-,Frame Type I
-Iec104_Deal_I-, error asdu addr(0)(6800)
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,0), Send(0,53)
-Iec104_Deal_SN-, error,send last(52),now(52). recv last(52),now(0)
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,53)
-Iec104_Deal_I-, error Type(110)
-Iex104_Receive-,Frame Type U
>Iec104_Deal_U<, function STOPDT
IEC10X_Enqueue,Prio(0) elementNum(0)len(6)(6)
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,53)
++++Asdu Type Firmware Update...
update flag error! need:1,flag:72
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,53)
++++Asdu Type Firmware Update...
-Iec104_Deal_FirmUpdate-,data:28673,Len:17 error cot:
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,53)
-Iec104_Deal_I-, error Type(110)
-Iex104_Receive-,Frame Type U
>Iec104_Deal_U<, function STOPDT
IEC10X_Enqueue,Prio(0) elementNum(1)len(6)(6)
-Iex104_Receive-,Frame Type I
-Iec104_Deal_I-, error asdu addr(0)(6800)
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,0), Send(0,53)
-Iec104_Deal_SN-, error,send last(52),now(52). recv last(52),now(0)
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,53)
-Iec104_Deal_I-, error Type(110)
-Iex104_Receive-,Frame Type U
>Iec104_Deal_U<, function STOPDT
IEC10X_Enqueue,Prio(0) elementNum(2)len(6)(6)
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,53)
++++Asdu Type Firmware Update...
update flag error! need:1,flag:72
-Iex104_Receive-,Frame Type U
>Iec104_Deal_U<, function TESTER ACK
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,53)
-Iec104_Deal_I-, error Type(110)
-Iex104_Receive-,Frame Type U
>Iec104_Deal_U<, function STOPDT
IEC10X_Enqueue,Prio(0) elementNum(3)len(6)(6)
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,52), Send(0,53)
++++Asdu Type Firmware Update...
update flag error! need:1,flag:72
-Iex104_Receive-,Frame Type I
Receive Pakage I(52,65), Send(0,53)
++++Asdu Type Firmware Update...  
-Iec104_Deal_FirmUpdate-,data:1,Len:0,seek:0 
ASAN:SIGSEGV
=================================================================
==29593==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000000000 bp 0x7fff4b4c5720 sp 0x7fff4b4c5618 T0)         ==29593==Hint: pc points to the zero page.

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 ??
==29593==ABORTING

SEGV in function Iec104_Deal_FirmUpdate

Hello. I built protocol IEC104 in my ubuntu16.04 machine with AddressSanitizer(export CFLAGS="-g -fsanitize=address" CXXFLAGS="-g -fsanitize=address" LDFLAGS="-fsanitize=address" before make) .

And I use prenny desock tool to build channels socket communication to the console.

But when I use the following data ( here in hexadecimal format for easy understanding but must be inputted as binary format file ) as the input to the server socket 10000, there will be a SEGV during the running.
68:e0:40:00:00:83:80:68 10:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:00 00:00:00:00:00:00:00:83 80:00:08

The way I built iec104_monitor is as you sad here, just cut the main function to the bottom in ./test/main.c and change the route of source files in ./test/Makefile.

The command line is as follows:
LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libasan.so.2:/root/preeny/x86_64-linux-gnu/desock.so" ./iec104_monitor -m server -n 1 < ./test_input
where
/usr/lib/x86_64-linux-gnu/libasan.so.2 is the lib of asan,
/root/preeny/x86_64-linux-gnu/desock.so is the lib of preeny desock
./test_input is the binary format file which contains the test input as mentioned above in hexadecimal format for easy understanding.

The run time error information is:

Register "Linux" IEC104 Success, < HuiXing 2014-2015 > ...
mode :(0), port: (0), ip: (), station num: (1) 
Iec104 Server Mode 
Iec104 Socket Ok(10000) !
Iec104 Bind Ok(10000) !
Iec104 Listen Ok(10000)
Accept ok!
Server start get connect from 0 : 0x2328
#####################received 
[DumpHEX]Length:43 
68:e0:40:00:00:83:80:68    10:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00    00:00:00:00:00:00:00:00
00:00:00:00:00:00:00:83    80:00:08
-Iex104_Receive-,Frame Type I 
Receive Pakage I(32,16768), Send(0,0)
++++Asdu Type Firmware Update... 
-Iec104_Deal_FirmUpdate-,data finish:0,Len:208,Total Len:0 
ASAN:SIGSEGV
=================================================================
==26583==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000000000 bp 0x000000000000 sp 0x7fb0d0cfe4e8 T1)
==26583==Hint: pc points to the zero page.

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 ??
Thread T1 created by T0 here:
    #0 0x7fb0d4376253 in pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x36253)
    #1 0x4020a9 in main /root/feilong/libiec104_fuzz/asan-mode/IEC10X/main.c:299

==26583==ABORTING

I use gdb to debug it and the information is as following:

Thread 2 "iec104_monitor" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff37ff700 (LWP 19690)]
0x0000000000000000 in ?? ()
(gdb) backtrace
#0  0x0000000000000000 in ?? ()
#1  0x000000000040898d in Iec104_Deal_FirmUpdate (asdu=asdu@entry=0x7ffff37fe886, Len=Len@entry=226 '\342') at ../IEC10X/Iec104.c:1129
#2  0x000000000040a631 in Iec104_Deal_I (Iec104Data=Iec104Data@entry=0x7ffff37fe880, len=len@entry=226) at ../IEC10X/Iec104.c:1208
#3  0x000000000040adac in Iex104_Receive (buf=buf@entry=0x7ffff37fe880 "h\340@", len=len@entry=43) at ../IEC10X/Iec104.c:1305
#4  0x000000000040fe67 in Iec104_main (arg=<optimized out>) at main.c:138
#5  0x00007ffff6a306ba in start_thread (arg=0x7ffff37ff700) at pthread_create.c:333
#6  0x00007ffff676641d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
(gdb) 
#0  0x0000000000000000 in ?? ()
#1  0x000000000040898d in Iec104_Deal_FirmUpdate (asdu=asdu@entry=0x7ffff37fe886, Len=Len@entry=226 '\342') at ../IEC10X/Iec104.c:1129
#2  0x000000000040a631 in Iec104_Deal_I (Iec104Data=Iec104Data@entry=0x7ffff37fe880, len=len@entry=226) at ../IEC10X/Iec104.c:1208
#3  0x000000000040adac in Iex104_Receive (buf=buf@entry=0x7ffff37fe880 "h\340@", len=len@entry=43) at ../IEC10X/Iec104.c:1305
#4  0x000000000040fe67 in Iec104_main (arg=<optimized out>) at main.c:138
#5  0x00007ffff6a306ba in start_thread (arg=0x7ffff37ff700) at pthread_create.c:333
#6  0x00007ffff676641d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:109
(gdb) 

Stack-buffer-overflow in function Iec104_Deal_I

I used Clang 5.0 and AddressSanitizer (export CFLAGS="-g -fsanitize=address" CXXFLAGS="-g -fsanitize=address" LDFLAGS="-fsanitize=address" before make) to build IEC104, this file can cause stack buffer overflow in the function Iec104_Deal_I in Iec104.c:

To compile the program, we modified the following two files:

diff --git a/test/Makefile b/test/Makefile
index cfcb1ff..5a19b05 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -1,15 +1,22 @@
 
-TOPDIR = ../../../../../..
+TOPDIR = ../
 INSTALLDIR = /usr/sbin
 #LIBDIR = /lib/
-MODULE_PATH=$(TOPDIR)/Module/IEC10X
+MODULE_PATH=$(TOPDIR)/IEC10X
 APP_PATH=$(TOPDIR)/Product/PollutionFlashover/AccessDevice/code/TEST/Iec104
 
+
+# CC = afl-clang-fast
 CC = gcc
 
+
+CFLAGS += -g -fsanitize=address
+CXXFLAGS += -g -fsanitize=address
+
 CFLAGS +=-I$(MODULE_PATH) -lpthread
 CFLAGS +=-I$(APP_PATH)
 
+
 OBJ=iec104_monitor
diff --git a/test/main.c b/test/main.c
index 19cc5a5..c6012d9 100644
--- a/test/main.c
+++ b/test/main.c
@@ -39,114 +39,6 @@ void Iec104_printhelp(void)
     printf("\n");
 }
 
-int main(int argc, char *argv[]){
-
-    pthread_t tid1,tid2; 
-    int err;  
-    void *tret;  
-    SocketArg_T Arg1;
-    unsigned int addr1 = 0,addr2 = 0;
-    int opt;  
-    char *optstring = "p:d:n:m:h";  
-    unsigned short port1 = 10000;
-    unsigned short port2 = 10001;
-    addr1 =  inet_addr("192.168.1.114");
-    addr2 =  inet_addr("192.168.1.114");
-    uint32_t Addr = 0,i;
-    void *ptemp = NULL;
-    
-    Arg1.port = 10000;
-    Arg1.addr = addr1;
-    
-    uint8_t mode = SOCKET_MODE_CLIENT;
-    uint8_t DstIp[32] = {0};
-    uint32_t Port = 0;
-    uint32_t NumSta = 0;
-    
-    ClientInfo_T clientinfo;
- 
-    Stm32f103RegisterIec10x(); 
-
-    while ((opt = getopt(argc, argv, optstring)) != -1){ 
-    #if 0 
-        printf("opt = %c\n", opt);  
-        printf("optarg = %s\n", optarg);  
-        printf("optind = %d\n", optind);  
-    #endif    
-        switch(opt){
-            case 'h':
-                Iec104_printhelp();
-                return;
-            case 'd':
-                if(optarg == NULL){
-                    printf("-d need argument \n");
-                    break;
-                }
-                Addr =  inet_addr(optarg);
-                strcpy(DstIp,optarg);
-                break;
-            case 'm':
-                if(strcmp("server", optarg) == 0)
-                    mode = SOCKET_MODE_SERVER;
-                else if(strcmp("client", optarg) == 0)
-                    mode = SOCKET_MODE_CLIENT;
-                else{
-                    LOG("mode error (%s) \n",optarg);
-                    return;
-                }
-                break; 
-            case 'p':
-                if(optarg == NULL){
-                    printf("-p need argument \n");
-                    break;
-                }
-                sscanf(optarg, "%d", &Port);
-                break;
-            case 'n':
-                if(optarg == NULL){
-                    printf("-n need argument \n");
-                    break;
-                }
-                sscanf(optarg, "%d", &NumSta);
-                break;
-            default :
-                break;
-        }
-    }  
-    
-    LOG("mode :(%d), port: (%d), ip: (%s), station num: (%d) \n",mode, Port,DstIp,NumSta);   
-    
-    pthread_mutex_init(&mutex,NULL);
-    pthread_mutex_init(&mutex2,NULL);
-    
-    if(NumSta<=0 || NumSta>10000){
-    
-        LOG("station number error:%d \n",NumSta);
-    } 
-    
-    if(mode == SOCKET_MODE_SERVER){
-        LOG("Iec104 Server Mode \n");
-        err=pthread_create(&tid1,NULL,Iec104_main,&Arg1);
-        if(err!=0)  {  
-            LOG("pthread_create error:%s\n",strerror(err));  
-            exit(-1);  
-        } 
-    }else if(mode == SOCKET_MODE_CLIENT){
-        LOG("Iec104 Client Mode \n");
-        for(i=0; i<NumSta; i++){
-            clientinfo.ClientId = i;
-            clientinfo.socketfd = 0;
-            err=pthread_create(&tid1,NULL,Iec104_Client,&clientinfo);
-            if(err!=0)  {  
-                printf("pthread_create error:%s\n",strerror(err));  
-                exit(-1);  
-            } 
-        }
-    }
-    while(1);
-
-    return 0;
-}
 
 void DumpHEX(uint8_t *buffer, uint32_t len){
 
@@ -315,4 +207,115 @@ void *Iec104_Client(void *arg)
     close(socketfd); 
  
     exit(0);  
+}
+
+
+
+int main(int argc, char *argv[]){
+
+    pthread_t tid1,tid2; 
+    int err;  
+    void *tret;  
+    SocketArg_T Arg1;
+    unsigned int addr1 = 0,addr2 = 0;
+    int opt;  
+    char *optstring = "p:d:n:m:h";  
+    unsigned short port1 = 10000;
+    unsigned short port2 = 10001;
+    addr1 =  inet_addr("192.168.1.114");
+    addr2 =  inet_addr("192.168.1.114");
+    uint32_t Addr = 0,i;
+    void *ptemp = NULL;
+    
+    Arg1.port = 10000;
+    Arg1.addr = addr1;
+    
+    uint8_t mode = SOCKET_MODE_CLIENT;
+    uint8_t DstIp[32] = {0};
+    uint32_t Port = 0;
+    uint32_t NumSta = 0;
+    
+    ClientInfo_T clientinfo;
+ 
+    Stm32f103RegisterIec10x(); 
+
+    while ((opt = getopt(argc, argv, optstring)) != -1){ 
+    #if 0 
+        printf("opt = %c\n", opt);  
+        printf("optarg = %s\n", optarg);  
+        printf("optind = %d\n", optind);  
+    #endif    
+        switch(opt){
+            case 'h':
+                Iec104_printhelp();
+                return;
+            case 'd':
+                if(optarg == NULL){
+                    printf("-d need argument \n");
+                    break;
+                }
+                Addr =  inet_addr(optarg);
+                strcpy(DstIp,optarg);
+                break;
+            case 'm':
+                if(strcmp("server", optarg) == 0)
+                    mode = SOCKET_MODE_SERVER;
+                else if(strcmp("client", optarg) == 0)
+                    mode = SOCKET_MODE_CLIENT;
+                else{
+                    LOG("mode error (%s) \n",optarg);
+                    return;
+                }
+                break; 
+            case 'p':
+                if(optarg == NULL){
+                    printf("-p need argument \n");
+                    break;
+                }
+                sscanf(optarg, "%d", &Port);
+                break;
+            case 'n':
+                if(optarg == NULL){
+                    printf("-n need argument \n");
+                    break;
+                }
+                sscanf(optarg, "%d", &NumSta);
+                break;
+            default :
+                break;
+        }
+    }  
+    
+    LOG("mode :(%d), port: (%d), ip: (%s), station num: (%d) \n",mode, Port,DstIp,NumSta);   
+    
+    pthread_mutex_init(&mutex,NULL);
+    pthread_mutex_init(&mutex2,NULL);
+    
+    if(NumSta<=0 || NumSta>10000){
+    
+        LOG("station number error:%d \n",NumSta);
+    } 
+    
+    if(mode == SOCKET_MODE_SERVER){
+        LOG("Iec104 Server Mode \n");
+        err=pthread_create(&tid1,NULL,Iec104_main,&Arg1);
+        if(err!=0)  {  
+            LOG("pthread_create error:%s\n",strerror(err));  
+            exit(-1);  
+        } 
+    }else if(mode == SOCKET_MODE_CLIENT){
+        LOG("Iec104 Client Mode \n");
+        for(i=0; i<NumSta; i++){
+            clientinfo.ClientId = i;
+            clientinfo.socketfd = 0;
+            err=pthread_create(&tid1,NULL,Iec104_Client,&clientinfo);
+            if(err!=0)  {  
+                printf("pthread_create error:%s\n",strerror(err));  
+                exit(-1);  
+            } 
+        }
+    }
+    while(1);
+
+    return 0;
 }
\ No newline at end of file

Then compile it by following command:

cd test && make

I run the program with the help of preeny(Channels socket communication to the console) by the following command:

LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.2:/root/preeny/x86_64-linux-gnu/desock.so ./iec104_monitor -m server < crash

Here is ASAN information:

==20667==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7f2ee8dfee6d at pc 0x000000409054 bp 0x7f2ee8dfe610 sp 0x7f2ee8dfe600
READ of size 2 at 0x7f2ee8dfee6d thread T1
    #0 0x409053 in Iec104_Deal_I ..//IEC10X/Iec104.c:1175
    #1 0x40972b in Iex104_Receive ..//IEC10X/Iec104.c:1305
    #2 0x40b661 in Iec104_main /root/feilong/4-3-104/IEC104/test/main.c:139
    #3 0x7f2eebf6d6b9 in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76b9)
    #4 0x7f2eebca341c in clone (/lib/x86_64-linux-gnu/libc.so.6+0x10741c)

Address 0x7f2ee8dfee6d is located in stack of thread T1 at offset 1853 in frame
    #0 0x40b12a in Iec104_main /root/feilong/4-3-104/IEC104/test/main.c:72

  This frame has 6 object(s):
    [32, 36) 'sin_size'
    [96, 100) 'on'
    [160, 168) 'tid1'
    [224, 240) 's_add'
    [288, 304) 'c_add'
    [352, 1852) 'Iec104_RecvBuf' <== Memory access at offset 1853 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
Thread T1 created by T0 here:
    #0 0x7f2eec3dd253 in pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.2+0x36253)
    #1 0x40c190 in main /root/feilong/4-3-104/IEC104/test/main.c:301
    #2 0x7f2eebbbc82f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)

SUMMARY: AddressSanitizer: stack-buffer-overflow ..//IEC10X/Iec104.c:1175 Iec104_Deal_I
Shadow bytes around the buggy address:
  0x0fe65d1b7d70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe65d1b7d80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe65d1b7d90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe65d1b7da0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe65d1b7db0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x0fe65d1b7dc0: 00 00 00 00 00 00 00 00 00 00 00 00 00[04]f3 f3
  0x0fe65d1b7dd0: f3 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00
  0x0fe65d1b7de0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe65d1b7df0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe65d1b7e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x0fe65d1b7e10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Heap right redzone:      fb
  Freed heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack partial redzone:   f4
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
==20667==ABORTING

Build Issue

Hi, it seems that this project can not be built directly. To compile it, the following two files should be modified:

The directory in the test/Makefile should be modified like this.

The main function in test/main.c should be moved to the end of file like this.

The project after modification can be found in grandnew/IEC104.

stack-buffer-overflow at IEC10x/Iec104.c

I used gcc 5.4.0 with CFLAGS=-g -fsanitize=address CXXFLAGS=-g -fsanitize=address LDFLAGS=-fsanitize=address to compile the IEC104, and use LD_PRELOAD=/root/preeny/x86_64-linux-gnu/desock.so ./iec104_monitor -m server -n 1 < test_case to run the program, whileI found a stack-buffer-overflow in IEC10x/Iec104.c, Iec104_Deal_I

Snip Iec104.c:1175

    /* check asdu addrest */
    if(Iec10x_Sta_Addr != asdu->_addr){
        LOG("-%s-, error asdu addr(%x)(%x) \n" ,__FUNCTION__ ,Iec10x_Sta_Addr,asdu->_addr);
        return RET_ERROR;
    }

It looks like you do not check the value of Iec10x_Sta_Addr, when it's value become unexpect, there will be a stack-buffer-overflow, which cause the program exit, it is advisble to ensure the value of Iec10x_Sta_Addr limited in a safe range.

ASAN OUTPUT

==10033==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff99ddd2dd at pc 0x0000004b95c1 bp 0x7fff99ddca80 sp 0x7fff99ddca70  READ of size 2 at 0x7fff99ddd2dd thread T0                                                                                                      #0 0x4b95c0 in Iec104_Deal_I ../IEC10X/Iec104.c:1175
    #1 0x4b9c11 in Iex104_Receive ../IEC10X/Iec104.c:1307
    #2 0x4be985 in Iec104_main /root/iec/Polar_104/test/main.c:423
    #3 0x405e53 in main /root/iec/Polar_104/test/main.c:629
    #4 0x7fe09fcb782f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
    #5 0x406238 in _start (/root/temp/iec/have_tested/Polar_104/test/iec104_monitor+0x406238)

Address 0x7fff99ddd2dd is located in stack of thread T0 at offset 1789 in frame                                                                 #0 0x4be39f in Iec104_main /root/iec/Polar_104/test/main.c:255

  This frame has 5 object(s):
    [32, 36) 'sin_size'
    [96, 100) 'on'
    [160, 176) 's_add'
    [224, 240) 'c_add'
    [288, 1788) 'Iec104_RecvBuf' <== Memory access at offset 1789 overflows this variable                                                   HINT: this may be a false positive if your program uses some custom stack unwind mechanism or swapcontext
      (longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow ../IEC10X/Iec104.c:1175 Iec104_Deal_I
Shadow bytes around the buggy address:
  0x1000733b3a00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000733b3a10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000733b3a20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000733b3a30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x1000733b3a40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x1000733b3a50: 00 00 00 00 00 00 00 00 00 00 00[04]f3 f3 f3 f3                                                                             0x1000733b3a60: f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00                                                                             0x1000733b3a70: f1 f1 f1 f1 04 f4 f4 f4 f2 f2 f2 f2 04 f4 f4 f4                                                                             0x1000733b3a80: f2 f2 f2 f2 00 f4 f4 f4 f2 f2 f2 f2 00 f4 f4 f4                                                                             0x1000733b3a90: f2 f2 f2 f2 00 04 f4 f4 f2 f2 f2 f2 00 00 00 00                                                                             0x1000733b3aa0: f3 f3 f3 f3 f3 f3 f3 f3 00 00 00 00 00 00 00 00                                                                           Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07
  Heap left redzone:       fa                                                                                                                 Heap right redzone:      fb                                                                                                                 Freed heap region:       fd                                                                                                                 Stack left redzone:      f1                                                                                                                 Stack mid redzone:       f2
  Stack right redzone:     f3                                                                                                                 Stack partial redzone:   f4                                                                                                                 Stack after return:      f5                                                                                                                 Stack use after scope:   f8                                                                                                                 Global redzone:          f9                                                                                                                 Global init order:       f6                                                                                                                 Poisoned by user:        f7                                                                                                                 Container overflow:      fc                                                                                                                 Array cookie:            ac                                                                                                                 Intra object redzone:    bb                                                                                                                 ASan internal:           fe                                                                                                               ==10033==ABORTING

SEGV in function Iec104_Deal_FirmUpdate

I used gcc 5.4.0 with CFLAGS=-g -fsanitize=address CXXFLAGS=-g -fsanitize=address LDFLAGS=-fsanitize=address to compile the IEC104, and use LD_PRELOAD=/root/preeny/x86_64-linux-gnu/desock.so ./iec104_monitor -m server -n 1 < test_case to run the program, while I found a SEGV in IEC10X/Iec104.c function Iec104_Deal_FirmUpdate.

here is the code:

case IEC10X_COT_DATA_FIN:
            if(FirmFlagCount == FlagNum){
                LOG("-%s-,data finish:%d,Len:%d,Total Len:%d \n",__FUNCTION__,FlagNum,DataLen,Iec10x_Update_SeekAddr);
                ret = IEC10X->CheckFirmware(FirmwareType, Iec10x_Update_SeekAddr);
                if(ret == RET_SUCESS){
                    Iec104_BuildDataAck(TI, IEC10X_COT_DATA_FIN_ACK, FirmwareType, FlagNum,1);
                    IEC10X->UpdateFirmware(FirmwareType);
                }else{
                    /* check firmware error ,terminal update */
                    Iec104_BuildDataAck(TI, IEC10X_COT_ACT_TERMINAL, FirmwareType, 0,1);
                } 
	}

seems that when FirmwareType and Iec10x_Update_SeekAddr become 0, the CheckFirmware will not create successfully, which is caused by some part of asdu become 0.

the ASAN output

Register "Linux" IEC104 Success, < HuiXing 2014-2015 > ...
mode :(0), port: (0), ip: (), station num: (1)
Iec104 Server Mode
Iec104 Socket Ok(10000) !
Iec104 Bind Ok(10000) !
Iec104 Listen Ok(10000)
feilong:Iec104 Listen Ok(10000)
feilong:Waiting for connection
Accept ok!
Server start get connect from 0 : 0x2328
#####################received
[DumpHEX]Length:43
68:e0:40:00:00:83:80:68    10:00:00:00:00:00:00:00
00:00:00:00:00:00:00:00    00:00:00:00:00:00:00:00
00:00:00:00:00:00:00:83    80:00:08
-Iex104_Receive-,Frame Type I
Receive Pakage I(32,16768), Send(0,0)
++++Asdu Type Firmware Update...
-Iec104_Deal_FirmUpdate-,data finish:0,Len:208,Total Len:0
log for finshss0            0
ASAN:SIGSEGV
=================================================================
==27310==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x000000000000 bp 0x7ffda2681960 sp 0x7ffda2681868 T0)         ==27310==Hint: pc points to the zero page.

AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 ??
==27310==ABORTING

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.