编写ttyUSB snooper失败

时间:2016-10-01 17:24:22

标签: serial-port hardware reverse-engineering hardware-interface

摘要:我正在编写一个ttyUSB窥探器。该代码应该从串行端口读取(2)数据并将其写入(2)到另一个串行端口。从串口读取可以很好地使用/ bin / cat,但是我的代码失败了。

硬件设置是:我制作了一条FTDI交叉电缆,将一端作为Com2放在Windows XP机器中,另一端放在现代Linux机器上作为/ dev / ttyUSB0。 Linux机器有一个USB转串口电缆,显示为/ dev / ttyUSB1。它连接到我试图窥探的实际硬件单元。我验证了,硬件效果很好。

这部分有效:我会" cat / dev / ttyUSB0>的/ tmp /数据"然后让WinXP机器通过Com2"发出"从设备读取,并发送以下六(6)字节数据。

\x02\x01\x40\x00\x0a\x9e

此"数据包"被发送4次左右,有一点点延迟,这似乎是WinXP代码只是尝试了几次。如果我只重播一次,它就可以了。

如果我只是做" cat / tmp / data> / dev / ttyUSB1",硬件设备将正确响应,表明它已收到命令。太好了!

问题和我的代码:我正在编写一些代码在Linux机器上运行,它将从/ dev / ttyUSB0读取(2)并将其写入/ dev / ttyUSB1,反之亦然。但是,由于某些未知原因,它只会在第一个"数据包"中接收4个字节,然后在后续3个尝试中接收5个字节。有时,5个字节会略微出现"损坏",这意味着我看到\ xffffff表示最后一个字节或倒数第二个字节。这是我的代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <strings.h>

void hexdump(char *data, int size) {
    for (size_t i = 0; i < size; ++i)
        printf("%02x ", data[i]);
    putchar('\n');
}

int main() {
    int fdzero;
    int fdone;

    int maxfd;

    fd_set sockrd;
    struct timeval timer;

    char data[10];
    int size;
    char tmp;

    fdzero = open("/dev/ttyUSB0", O_RDWR);
    if (fdzero == -1) {
        perror("Failed to open /dev/ttyUSB0");
        return 1;
    }

    fdone =  open("/dev/ttyUSB1", O_RDWR);
    if (fdone == -1) {
        perror("Failed to open /dev/ttyUSB1");
        return 1;
    }

    if (fdzero > fdone)
        maxfd = fdzero;
    else
        maxfd = fdone;

    printf("Enter loop\n");
    for(;;) {
        bzero(data, 10);
//      fflush(NULL);
        FD_ZERO(&sockrd);
        FD_SET(fdzero, &sockrd);
        FD_SET(fdone,  &sockrd);

        timer.tv_sec = 60;
        timer.tv_usec = 0;

        select(maxfd+1, &sockrd, NULL, NULL, &timer);

        if (FD_ISSET(fdzero, &sockrd)) {

            size = read(fdzero, data, 10);
            if (size == -1) {
                perror("Failed to read /dev/ttyUSB0");
                break;
            }

            size = write(fdone, data, size); 
            if (size == -1) {
                perror("Failed to write to /dev/ttyUSB1");
                break;
            }
            printf("ttyUSB0 -> ttyUSB1: %d\n", size);
        }


        // This portion does not trigger yet, but its a mirror
        // Yes, I know...bad code :(
        else {
            size = read(fdone, data, 10);
            if (size == -1) {
                perror("Failed to read /dev/ttyUSB1");
                break;
            }
            size = write(fdzero, data, size);
            if (size == -1) {
                perror("Failed to write to /dev/ttyUSB0");
                break;
            }
            printf("ttyUSB1 -> ttyUSB0: %d\n", size);
        }

        // Used to monitor what is read()/write()
        hexdump(data, size);
    }

    return 0;
}

当我实际运行此代码时,我看到了:

# cc snoop.c -o snoop
# ./snoop
Enter loop
ttyUSB0 -> ttyUSB1: 4
02 00 40 ffffff9e 
ttyUSB0 -> ttyUSB1: 4
02 00 40 ffffff9e 
ttyUSB0 -> ttyUSB1: 4
02 00 40 ffffff9e 
ttyUSB0 -> ttyUSB1: 5
01 02 00 40 ffffff9e 
ttyUSB0 -> ttyUSB1: 5
01 02 00 40 ffffff9e 
ttyUSB0 -> ttyUSB1: 5
01 02 00 40 ffffff9e

请注意,在任何给定时间只接收4个或5个字节并随后发送。不是6.另外,请注意&#34;数据包&#34;是扭曲的。世界上会发生什么?

理性如果您感兴趣:我的旧软件只能在Windows XP上运行,不能在VM中运行(这是一个已知问题)。我很想捕捉通过串口的流量。我刚刚购买了一台WinXP机器。

1 个答案:

答案 0 :(得分:0)

好的,所以你的两个问题在这里:

  

有时候,5个字节会略微“损坏”,这意味着我会看到\ xffffff表示最后一个或倒数第二个字节。

这是因为printf如何解释进来的数据(here可能感兴趣)。它是作为hexdump(char* data, int len)传递的,已签名。在这种情况下,正在解释高阶位。要修复此部分,您的hexdump(unsigned char* data, int len)应该是uint8_t或使用字段大小的类型,例如hexdump(uint8_t* data, int len),以便您的签名看起来像0x0A

  

但是,由于某些未知原因,它只会在第一个“数据包”中接收4个字节,然后在随后的3次尝试中接收5个字节。

这几乎可以肯定是因为您没有在串行端口上设置任何设置。您拥有的其中一个字符是struct termios newio; if( tcgetattr( fd, &newio ) < 0 ){ /* error handling here */ } /* Set some default settings */ newio.c_iflag |= IGNBRK; newio.c_iflag &= ~BRKINT; newio.c_iflag &= ~ICRNL; newio.c_oflag = 0; newio.c_lflag = 0; newio.c_cc[VTIME] = 0; newio.c_cc[VMIN] = 1; /* Set our baud rate */ cfsetospeed( &newio, B9600 ); cfsetispeed( &newio, B9600 ); /* Character size = 8 */ newio.c_cflag &= ~CSIZE; newio.c_cflag |= CS8; /* One stop bit */ newio.c_cflag &= ~CSTOPB; /* Parity = none */ newio.c_iflag &= ~IGNPAR; newio.c_cflag &= ~( PARODD | PARENB ); newio.c_iflag |= IGNPAR; /* No flow control */ newio.c_iflag &= ~( IXON | IXOFF | IXANY ); /* Set our serial port settings */ if( tcsetattr( fd, TCSANOW, &newio ) < 0 ) { /* error handling code here */ } ,它是换行符。这可以被串行端口驱动程序忽略,也可以一起转换为不同的字符。要解决此问题,您必须将串行端口设置设置为原始设置,而不是翻译任何进入的字符。我通常会执行以下操作:

file1.ts
import { Component } from "@angular/core";
@Component({
    selector: "search",
    templateUrl: '<div>Hello{{testData}}</div>'
})

export class File1Component{
public testData = "Hello";

}

file2.ts
import { Component } from "@angular/core";
@Component({
    selector: "profile",
    templateUrl: '<div>Hello</div>'
})

export class File2Component{


}

如果您不想以这种方式设置串口设置,我写了一个this,它应该为您提取小细节。