Наши партнеры



Статьи‎ > ‎Foscam‎ > ‎

Ломаем Foscam FI8908W

Статья для тех, кому интересно покопаться в IP камере FI8908W. Все камеры от Foscam устроены внутренне одинаково при внешних различиях. Очевидно, внутри имеется микропроцессор ARM архитектуры с сетевой WiFi платой и видеокамерой. Операционная система - Linux. Отсюда следует, что под этот компьютер можно и программировать.
Поизучаем файлы прошивки в шестнадцатиричном редакторе. У фоскама есть два различных файла для прошивки. Один - ядро системы и второй - веб-сервер. Первый файл кажется наиболее хитрым, который трудно вскрыть. Возьмемся за веб интерфейс камеры.
Он выглядит следующим образом:
 
Offset:     Data Type/Size:    Description/Value/Etc:
0x0000     INT32_LE     Size of file
0x0004     Byte[4]  Version Number, each byte a min/minor value (2.4.8.12)
0x0008     Char[21]     File Description

{ ## Repeats until End-Of-File

+0x000     INT32_LE     Length of File Name
+0x004     Char[...]   File Name
+(Filelen)  Byte     File Type (0 = directory, 1 = file)

{ If 'File Type' == 1 then
+0x001     INT32_LE     Length of File Data
+0x004     Char[...]     File Data
}

}

На основе этого можно написать программку, которая парсит этот файл и вытаскивает файлы из бинарника:
 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>

int main(int argc, char **argv) {
FILE *f = NULL;
int len = 0, type = 0;
char src_file[512], dst_file[512], *data = NULL;
int max_data = 0;

if ( (f = fopen(argv[1], "rb")) == NULL)
exit(-1);

fseek(f, 0, SEEK_END);
int file_len = ftell(f);
fseek(f, 0, SEEK_SET);

fread(&len, 1, 4, f);
if (len != file_len) {
fprintf(stderr, "File size doesn't match that reported in the header: %d/%d\n", len, file_len);
exit(-1);
}

fseek(f, 29, SEEK_SET); // seek to first file

while(!feof(f)) {
memset(src_file, 0, sizeof(src_file));
memset(dst_file, 0, sizeof(dst_file));

fread(&len, 1, 4, f); // read filename length
fread(src_file,1,len,f); // read filename
sprintf(dst_file, "%s%s", argv[2], src_file);

type = 0;
fread(&type, 1, 1, f); // read entry type
if (type == 0) {
if (mkdir(dst_file, 0770) != 0) {
fprintf(stderr, "Unable to write file: %s", dst_file);
exit(-1);
}
} else if (type == 1) {
FILE *f2 = fopen(dst_file, "wb");
if (f2 == NULL) {
fprintf(stderr, "Unable to write file: %s", dst_file);
exit(-1);
}

fread(&len, 1, 4, f); // read data length
if (len > max_data) {
data = realloc(data, len);
max_data = len;
if (data == NULL) {
fprintf(stderr, "Unable to allocate  data necessary to extract file.  Requested: %d bytes.\n", len);
exit(-1);
}
}
fread(data,1,len,f);

fprintf(stdout, "Extracting %s (%d bytes)...\n", src_file, len);
fwrite(data, 1, len, f2);
fclose(f2);
}
}

fclose(f);
free(data);
return 0;
}

Это исходинки на языке С, компилируемые под GCC. Если программка нужна под винду, можно закинуть файл в Visual Studio, исправить ошибки, если будут и сбилдить в консольное приложение.

На SourceForge заведен проект, который позволяет вытаскивать файлы из обоих бинарников. Опять же, исходники под линукс и компилятся в GCC. При случае можно легко переписать под винду на C#.