需要对这种 HCC 文件格式进行逆向工程的想法

逆向工程 结构体
2021-06-19 10:22:25

2015 年 1 月 17 日更新,

我们通过将 CSV 转换为 hcc 文件取得了一些进展;但是,MT5 正在删除该文件。附上我们的代码。有人可以帮助我们吗?

http://www.mediafire.com/download/n5454ao79mmqksf/CSVtoHCC.rar


有人能给我们一些关于如何破解这个 hcc 文件的提示吗?花了很长时间,但朋友能够确定其数据结构。有关 hcc 文件,请参阅下面的链接。

4 字节,分隔符,小端编码 18385028,十六进制(84 88 18 01)

4 字节,时间,可被 60 整除的整数

8 字节,双开盘价

8 字节,双最高价

8 字节,双最低价

8 字节,双收盘价

1 字节,字符 | 小整数点差

1 字节,字符 | 小整数滴答量

日期和时间格式为:2015.01.04 0:00

开盘价 = 1.23894 最高价 = 1.23904 最低价 = 1.23883 收盘价 = 1.23904 价格变动量 = 81

2015.01.04 0:00 1.23894 1.23904 1.23883 1.23904 81

提前谢谢了。

http://www.mediafire.com/download/2csbb4s3b9bjx8e/2015.hcc

2个回答

该文件似乎也包含“交易总和”字段。我稍微改进了我之前的程序:

/* version 1.2 - generates a CSV file on the desktop for another application to create a reverse engineered hcc file */
/* version 1.1 - includes header format and detects the number of data rows */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#pragma pack(1)
union header {
                struct {
                                char magic[2]; // 0x81 0x00
                                char label[64];
                                char something[18];
                                int nrows;
                } data;
                char rawbytes[189];
};

struct record {
                int separator;
                int time;
                double open, high, low, close;
                char additional[10]


};


void printint(char *buf, FILE *fpcsv,int size);
void dumpat(FILE *fp,FILE *fpcsv, int start);

int main(int argc, char **argv) {
                FILE *fp,*fpcsv;
                union header header;


                if ((fpcsv=fopen("C:\\Users\\Hello\\Desktop\\2015.csv", "w"))==NULL) {
                        perror("C:\\Users\\Hello\\Desktop\\2015.csv"); return 1;
                }
                if ((fp=fopen("C:\\Users\\Hello\\Desktop\\2015.hcc", "rb"))==NULL) {
                        perror("C:\\Users\\Hello\\Desktop\\2015.hcc"); return 1;
                }
                fseek(fp, 0x3be5-sizeof(header), 0);
                while (fread(&header, sizeof header, 1, fp)!=0) {
                                if ((header.data.magic[0]&0xff)!=0x81
                                ||   header.data.magic[1]!=0x00) {
                                                fprintf(stderr, "Bad header magic number at %08lx\n",
                                                                ftell(fp)-sizeof(header));
                                                exit(1);
                                }
                                fprintf(fpcsv,"Expect %d rows\n", header.data.nrows);
                                dumpat(fp,fpcsv, header.data.nrows);
                // dumpat(fp, 0x3be5);
                // dumpat(fp, 0xde1a);
                // dumpat(fp, 0x1e169);
                // dumpat(fp, 0x2e4a5);
                // dumpat(fp, 0x3bd7e);
                // dumpat(fp, 0x55c07);
                }
                fclose(fp);
                fclose(fpcsv);
}

void dumpat(FILE *fp,FILE *fpcsv, int nrows) {
                struct record data;
                int i, extra1, extra2, extra3, pos;
                time_t time;
                struct tm *tm;
                char timebuf[80];

                for (i=0; i<nrows; i++) {
                                if (fread(&data, sizeof(int), 1, fp)==0)
                                                break;
                                if ((data.separator & 0x00088884) != 0x00088884) {
                                                fprintf(stdout, "bad separator %08x at %lx\n",
                                                                data.separator, ftell(fp));
                                                break;
                                }
                                extra1=data.separator>>28;
                                extra2=((data.separator>>24)&0x0f);
                                extra3=((data.separator>>20)&0x0f);
                                fread(&data.time,  4 + 8 + 8 + 8 + 8 + extra3 + extra2 + extra1
                                                , 1, fp);
                                time=data.time;
                                tm=gmtime(&time);
                                strftime(timebuf, sizeof timebuf, "%Y-%m-%d %H:%M:%S", tm);
                                fprintf(fpcsv,"%s,%lf,%lf,%lf,%lf,", timebuf, data.open,
                                                data.high, data.low, data.close);
                                pos=0;
                                printint(data.additional+pos,fpcsv, extra3); pos+=extra3;
                                fprintf(fpcsv,",");
                                printint(data.additional+pos,fpcsv, extra2); pos+=extra2;
                                fprintf(fpcsv,",");
                                printint(data.additional+pos,fpcsv, extra1); pos+=extra1;
                                fprintf(fpcsv,"\n");

                }
}

void printint(char *buf,FILE *fpcsv, int size) {
                int val=0, scale=1;
                while (size--) {
                                val+=(*buf++&0xff)*scale;
                                scale<<=8;
                }
                 fprintf(fpcsv,"%5d", val);
}

结果开始于:

2015-01-02 10:00:00 1.205450 1.205450 1.205140 1.205160    31     9 22000000 
2015-01-02 10:01:00 1.205160 1.205210 1.205030 1.205030    31     6 35000000 
2015-01-02 10:02:00 1.205030 1.205030 1.204680 1.204730    51     9 54500000 
2015-01-02 10:03:00 1.204730 1.204750 1.203460 1.203850    81    18 65700000 
2015-01-02 10:04:00 1.203790 1.204210 1.203750 1.204210    79     9 85100000 
2015-01-02 10:05:00 1.204200 1.204210 1.204090 1.204170    41    10 38300000 
2015-01-02 10:06:00 1.204170 1.204570 1.204150 1.204150    52    13 46600000 
2015-01-02 10:07:00 1.204150 1.204460 1.204150 1.204380    44     8 53900000 
2015-01-02 10:08:00 1.204380 1.204380 1.203800 1.203800    52     9 70400000 
2015-01-02 10:09:00 1.203820 1.204010 1.203600 1.203900    72     9 76100000 

标题(包含EUR USD)似乎具有相同的大小,并且数据的开头似乎每次都在 D 之后 176 个字节,但我还不确定在哪里/如何找到它们中的第一个,以及在哪里存储到下一个标题的数据行数,所以我还不能摆脱那些幻数(数据开始的字节位置)。

拥有这个实际文件的输出会有所帮助。快速搜索后,我发现:

$ strings -e l 2015.hcc
Copyright 2001-2014, MetaQuotes Software Corp.
History
EURUSD
EURUSD
EURUSD
EURUSD
EURUSD
EURUSD

这导致了以下网站这个文件里有什么?使用明文攻击会更有效率。你有更多的示例文件吗?

使用binwalk没有透露任何信息,所以我猜这是一个简单的二进制格式,因为它包含 - 潜在的交易信息我敢打赌这是一个简单的格式(不涉及加密或混淆)。