来自中国分贝计的神秘字节码(可执行?)文件,其制造商已被黑客入侵和/或破产

逆向工程 可执行 字节码
2021-07-04 20:41:28

我最近从亚马逊买了一个分贝计(http://www.amazon.com/Sound-Measure-Tester-Pressure-Decibel/dp/B00CPKSE38/ref=sr_1_1?ie=UTF8&qid=1436376590&sr=8-1&keywords=wensn)将 db 测量值输出到 microsd 卡。我在电脑上打开 SD 卡的内容,遇到四个单独的 *.wsn 文件,其中两个是我创建的,另外两个显然是制造商在测试中制作的。无论如何,谷歌搜索了 .wsn 文件扩展名,除了所谓的“whoopsie 皮肤文件”之外什么都找不到,这似乎不是我要找的东西。谁能帮我找到解析这个文件的方法?我想它只包含一个包含两列(数据库级别和时间)的信息表

这是文件示例的链接。它是来自分贝计的仅几秒钟的时间序列数据。 https://drive.google.com/file/d/0B0yWXI3LgLr4ME1DeUs4SDFMX1E/view?usp=sharing

更新:db 测量设备的制造商是“wensn”,它清楚地说明了文件扩展名。到目前为止,我发现了两条线索:

但两者都用于解析来自设备的 *.tmp 文件的 USB 流,而不是静态 wsn 文件。我猜我可以利用这段代码来解析 wsn 文件,但我还不知道该怎么做。老实说,在这一点上我有点不知所措。

我首先发布了这个问题 meta.stackexchange,你可以在这里找到那个讨论预期的输出数据为柱状,时间和分贝水平,似乎表明这里

更新 2:我认为可能有一种方法可以使用“ sigrok ”实用程序来解码此文件,该实用程序用于读取来自科学传感器的各种串行输出。

4个回答

这是您的示例文件的十六进制转储:

00000000  1F DA 51 A0 19 5A 52 A0  19 DA 52 A0 28 5A 53 A0  ..Q..ZR...R.(ZS.
00000010  28 DA 53 A0 24 5A 54 A0  1A DA 54 A0 2A 5A 55 A0  (.S.$ZT...T.*ZU.
00000020  26 DA 55 A0 26 5A 56 A0  08 DA 56 A0 47 5A 57 A0  &.U.&ZV...V.GZW.
00000030  35 DA 57 A0 32 5A 58 A0  3B DA 58 A0              5.W.2ZX.;.X.

如您所见,该文件显然有一个模式,其中 4 个字节似乎重复: - 字节 1 上下变化,可能与声级有关 - 字节 2 在 DA 和 5A 之间交替 - 注意 DA 只是 5A设置了最高位 - 字节三似乎正在缓慢上升,可能是一个时间指示器 - 字节四是 A0,可能是时间的高位字节。

然而,如果没有关于已记录的声级的任何信息,或来自原始字节的一些预期值,每个猜测都很难验证。如果您可以使用设备附带的软件,用它打开文件,然后告诉我们该软件是如何处理这些数据的,那将会非常有帮助。

顺便说一句,德国供应商 Voelkner(他们信誉良好,我曾多次从他们那里购买)有该产品德文/英文 PDF 手册,最新版本指的是 www.omnitronic.com。该网站转发到销售该产品的商店,不再有库存,但仍有手册和软件下载页面. 该产品看起来略有不同,但具有相同的整体布局和关键位置,因此有理由假设它是在略有不同的塑料外壳中的相同电子设备,并且该软件可能适合您,甚至比您的设备随附的软件更好- 亚马逊评论说该软件是中文的,没有驱动程序;“我的”下载页面上的 zip 包括一个“Vista 驱动程序”文件夹和一个似乎支持英语的安装程序。

这是十六进制格式的文件(使用 vi 和 完成:%!xxd;我自己添加了列号):

          0 1  2 3  4 5  6 7  8 9  a b  c d  e f
0000000: 1fda 51a0 195a 52a0 19da 52a0 285a 53a0  ..Q..ZR...R.(ZS.
0000010: 28da 53a0 245a 54a0 1ada 54a0 2a5a 55a0  (.S.$ZT...T.*ZU.
0000020: 26da 55a0 265a 56a0 08da 56a0 475a 57a0  &.U.&ZV...V.GZW.
0000030: 35da 57a0 325a 58a0 3bda 58a0 0a         5.W.2ZX.;.X..

如您所见,具有奇数索引的字节都是da, a0, 5a, a0, 周期为 8 个字节(半行)。这看起来不像usb stream 上数据,因此该链接或 Python 项目可能不会对您有太大帮助:

在此处输入图片说明

此外,似乎是在列的计数器2a515253,...的列字节6并且a是相同的。e2的字节也相同,但有 2 个不同,表明这部分不是很好对齐。进一步逆向工程的更好对齐方式是将列移动e到最左边的位置左右。

您可以获得更大的样本,以查看da,a05a是否是常量,或者它们是计数器的一部分,或者可能是其他东西。例如,也可能它们实际上是测量的一部分,但在这里似乎是恒定的,因为测量时刻的声级是恒定的。

在任何情况下,似乎在这一点上,仅列048c携带数据。一旦您确认了该假设(通过查看更多数据),您就可以开始生成声音并查看您看到的数据与您生成的声音之间的关系。

考虑到制造商使用自己的名称作为扩展名,这个文件不太可能有一些常用的表格格式,所以我不能给你更多的提示。

关于十六进制编辑器的说明。如前所述,我将 vi 与 xxd 一起使用(即在 vi 中打开文件,然后:%!xxd)。但是,有很多十六进制编辑器,也适用于 Windows。我不知道有什么可以让你移动开始列,这对检查对齐很有用。

你的文件看起来像:

51A0
52A0
52A0
53A0
53A0

_

52A0 = 20:02:36
53A0 = 20:02:38 in dos time

如果它的 dos 时间是有意义的,为什么每个模式(51A0,52A0)显示 2 次,因为 dos 时间不接受奇数作为秒。

理论1:

我不认为任何自然的声音会变成 DA,5A,DA,5A,DA,5A,DA,5A,DA,5A。

所以我假设 DA 显示较低的部分,而 5A 是较高的部分。(DA=+0 和 5A=+1)

5A 52 A0 = 20:02:36
DA 52 A0 = 20:02:37
5A 53 A0 = 20:02:38
DA 53 A0 = 20:02:39

我不太了解测量声音,但我也可以根据第一个字节做出假设。但这可能是错误的,因为您没有提供有关您捕获的声音的任何信息。

第一个字节是您的文件中的最大值:0x47(71) 最小值:0x8(8)。

在亚马逊页面上写着 (30 ~ 130 Db)

8 不适合这些范围,所以我假设第一个字节是一个偏移量。

130-30=100 -> 0 > x > 100。

每 4 个字节都有以下信息:

struct Frame{
  char SoundOffset;
  char TimeOffset;
  char DosTime[2];
}

我为您的数据编写了示例代码。

#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <string>
#include <iostream>  
#include <fstream>
#include <iostream>

using namespace std;


struct DosTime{
    int hour, minute, second;
    DosTime(char a1, char a2){
        char y[2] = { a1, a2 };
        INT16 * b = (INT16*)y;
        second = 2 * (*b & 31);
        minute = (*b & 2016) >> 5;
        hour = (*b & 63488) >> 11;
    }
    DosTime(){
        hour = 0;
        minute = 0;
        second = 0;
    }
};
struct Frame{
    char SoundOffset;
    char TimeOffset;
    char DosTime[2];
};
struct ConvertedFrame{
    int soundDB;
    DosTime time;
    void print(){
        cout << "Sound Level: " << soundDB << " dB @ ";
        cout.fill('0'); cout.width(2); cout << time.hour;
        cout << ":";
        cout.fill('0'); cout.width(2); cout << time.minute;
        cout << ":";
        cout.fill('0'); cout.width(2); cout << time.second;
        cout << endl;
    }
};
int main(int argc, char* argv[])
{

    int bytecount = 0;

    ifstream inFile;
    inFile.open("FG8U0235.wsn", ios::in | ios::binary | ios::ate);
    inFile.seekg(0, ios::end);
    bytecount = inFile.tellg();
    inFile.seekg(0, ios::beg);

    char * buffer = new char[bytecount];
    inFile.read(buffer, bytecount);

    ConvertedFrame * frames = new ConvertedFrame[bytecount / 4];
    for (int i = 0; i < bytecount; i += 4){
        ConvertedFrame _con;
        Frame f;
        memcpy(&f, &buffer[i], 4);
        DosTime _t = DosTime(f.DosTime[0], f.DosTime[1]);
        if (f.TimeOffset == '\xDA')
            _t.second++;
        _con.time = _t;
        _con.soundDB = ((int)f.SoundOffset) + 30;
        frames[i / 4] = _con;
        _con.print();
    }
    system("pause");
    return 0;

}

哪些输出:

Sound Level: 61 dB @ 20:02:35
Sound Level: 55 dB @ 20:02:36
Sound Level: 55 dB @ 20:02:37
Sound Level: 70 dB @ 20:02:36
Sound Level: 70 dB @ 20:02:39
Sound Level: 66 dB @ 20:02:40
Sound Level: 56 dB @ 20:02:41
Sound Level: 72 dB @ 20:02:42
Sound Level: 68 dB @ 20:02:43
Sound Level: 68 dB @ 20:02:44
Sound Level: 38 dB @ 20:02:45
Sound Level: 101 dB @ 20:02:46
Sound Level: 83 dB @ 20:02:47
Sound Level: 80 dB @ 20:02:48
Sound Level: 89 dB @ 20:02:49

理论2:

在您给我们的网站 ( http://opensource.ebswift.com/RaspiMonitor/wensn/ ) 上,有这个函数 ( dB = (byte1 + ((byte2 & 3) * 256)) * 0.1 + 30 )我认为也许第二个字节实际上不是时间偏移,而是 dB 的第二个字节。

这使得 dB Float 而不是 Integer 更有意义。我从第二个理论中得到的输出感觉好多了,所以我认为这是正确的答案。

#define _CRT_SECURE_NO_WARNINGS
#include <Windows.h>
#include <string>
#include <fstream>
#include <iostream>

using namespace std;

struct DosTime{
    int hour, minute, second;
    INT16 data;
    DosTime(char a1, char a2){
        char y[2] = { a1, a2 };
        INT16 * b = (INT16*)y;
        second = 2 * (*b & 31);
        minute = (*b & 2016) >> 5;
        hour = (*b & 63488) >> 11;
        data = *b;
    }
    DosTime(){
        hour = 0;
        minute = 0;
        second = 0;
    }
};
struct Frame{
    char SoundOffset;
    char precisionOffset;
    char DosTime[2];
};
struct ConvertedFrame{
    float soundDB;
    DosTime time;
    void print(){
        cout << "Sound Level: ";
        cout << soundDB;
        if ((((int)soundDB) - soundDB) == 0) cout << ".0";
        cout << " dB @ ";
        cout.fill('0'); cout.width(2); cout << time.hour;
        cout << ":";
        cout.fill('0'); cout.width(2); cout << time.minute;
        cout << ":";
        cout.fill('0'); cout.width(2); cout << time.second;
        cout << endl;
    }
};
int main(int argc, char* argv[])
{
    int bytecount = 0;

    ifstream inFile;
    inFile.open("FG8U0235.wsn", ios::in | ios::binary | ios::ate);
    inFile.seekg(0, ios::end);
    bytecount = inFile.tellg();
    inFile.seekg(0, ios::beg);

    char * buffer = new char[bytecount];
    inFile.read(buffer, bytecount);


    ConvertedFrame * frames = new ConvertedFrame[bytecount / 4];


    INT16 lastTime = 0;
    for (int i = 0; i < bytecount; i += 4){
        ConvertedFrame _con;
        Frame f;
        memcpy(&f, &buffer[i], 4);
        DosTime _t = DosTime(f.DosTime[0], f.DosTime[1]);
        if (lastTime == _t.data) _t.second++;
        lastTime = _t.data;
        _con.time = _t;
        _con.soundDB = (f.SoundOffset + ((f.precisionOffset & 3) * 256)) * 0.1 + 30;
        frames[i / 4] = _con;
        _con.print();
    }
    system("pause");
    return 0;

}

输出:

Sound Level: 84.3 dB @ 20:02:34
Sound Level: 83.7 dB @ 20:02:36
Sound Level: 83.7 dB @ 20:02:37
Sound Level: 85.2 dB @ 20:02:38
Sound Level: 85.2 dB @ 20:02:39
Sound Level: 84.8 dB @ 20:02:40
Sound Level: 83.8 dB @ 20:02:41
Sound Level: 85.4 dB @ 20:02:42
Sound Level: 85.0 dB @ 20:02:43
Sound Level: 85.0 dB @ 20:02:44
Sound Level: 82.0 dB @ 20:02:45
Sound Level: 88.3 dB @ 20:02:46
Sound Level: 86.5 dB @ 20:02:47
Sound Level: 86.2 dB @ 20:02:48
Sound Level: 87.1 dB @ 20:02:49

注意: 要找出哪个是正确的,您需要将 dB 写到纸或其他东西中,然后与从两个代码中获得的输出进行比较。

如果您使用此代码并希望防止内存泄漏,您还需要清理 ConvertedFrame * 帧和 char * 缓冲区。我在凌晨 4 点写这段代码的速度非常快,只是为了测试理论。

我从亚马逊购买了分贝计 Koolertron SL1361,它生成文件 *.wsn,但软件不起作用,所以我使用此注释来理解。最后的理论 2 是对的,每个样本数据都是 4 个字节长。

假设 32 位(四字节)被命名为 bit31-0,这里我的解码:

Bit 31-24 & 17-16 Db 中的值(10 位),必须除以 10 再加上 30 才能得到正确的值 Bit 22 滤波模式 0=Fast 1=Slow Bit 21 滤波模式 0=A 1=C Bit 12-8 & 23 = 秒 Bit 7-3 = 小时 Bit 2-0 & 15-13 = 分钟

它们以正二进制编码。

一切正常。