Inhaltsverzeichnis

UTM - extract plx files

Hintergrund

Möchte wissen wie die UTM (eine Firewall von sophos) ein Backup erstellt/wiederherstellt.

Seitens sophos werden Perl-Scripte eingesetzt, die durch ActiveStates PerlApp als Binaries vorliegen. Ein einfaches entpacken wie bei anderen Lösungen ist nicht möglich.

Setup

VM1: Windows mit IDA Pro
VM2: Sophos UTM

Verbunden durch ein „internal Network“ von VirtualBox

Bisherige Erkenntnisse

Reversing

Ablauf (BFS)

0013d80: 7f3a 5baa 0200 0000 4038 0000 7000 a108  .:[.....@8..p...
0013d90: 810e 2ade 0974 65d1 f74e 2ee4 9fa8 28db  ..*..te..N....(.
0013da0: 9a5e 6b26 89a6 1068 b8fb 62a1 433f f4c4  .^k&...h..b.C?..
0013db0: 4d1e a356 9208 2789 5656 6df5 fe96 d198  M..V..'.VVm.....
0013dc0: f43c be7e e2cf e69b ca48 3c0d 8730 d2d4  .<.~.....H<..0..

Der Packer durchsucht sich selbst nach einem Magic value von 0x7f 0x3a 0x5b 0xaa 0x02 0x00 0x00 0x00. In Wirklichkeit sind dies zwei Magic values. 0x02 0x00 0x00 0x00 ist ein weitere um nicht an der falschen Stelle anzusetzen.

0x40 0x38 0x00 0x00, nach dem Magic, ist die Länge der Datei als auch gleichzeitig der XOR-Key

Heraus kommt eine BFS-File

00000000  ff 42 46 53 02 00 00 00  d0 37 00 00 08 00 00 00  |.BFS.....7......|

Ablauf (Post-BFS)

Das BFS-File ist ein Archive an sich. Es beinhaltet einen unbekannten Header, gefolgt von mehreren zlib-Elementen.

Entpacken kann man dies mit mittels binwalk -e.

Jedes dieser Elemente ist _nach_ dem entpacken jedoch erneut mit XOR bearbeitet. Der Key war durch ein Bruteforce jedoch leicht zu finden.
Er lautet 0xEA.

Heraus kommen Klartext-Dateien, nebst eigenen Abhängigkeiten des Packers auch diverse andere Perl-Module.

BFS-Dumper

Krater hat einen PoC geschrieben um BFS-Daten zu finden und zu XORn

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
void shift(unsigned char *buf);
void decodedata(FILE *f);
 
int main()
{
   FILE *f=fopen("backup.plx","rb");
 
   unsigned char buf[8]={0};
   unsigned char magic[]={0x7f,0x3a,0x5b,0xaa,0x02,0x00,0x00,0x00};
 
   while(!feof(f))
   {
      if(!memcmp(buf,magic,8))
      {
         printf("found!\n");
         decodedata(f);
         break;
      }
 
      shift(buf);
      fread(buf+7,1,1,f);
 
   }
 
   fclose(f);
   return 0;
}
 
void decodedata(FILE *f)
{
   unsigned int length;
   unsigned short offset;
 
   fread(&length,4,1,f);
   fread(&offset,2,1,f);
 
   printf("found %u bytes data at offset %u\n",length,offset);
 
   fseek(f,offset-(6+8),SEEK_CUR);
 
   unsigned char *data=(unsigned char*)malloc(length);
   fread(data,1,length,f);
 
   unsigned int *d=(unsigned int *)data;   
   for(int i=0;i<(length/4);i++)
   {
      d[i]^=length;   
   } 
 
   FILE *o=fopen("output.data","wb");
   fwrite(data,1,length,o);
   fclose(o);
}
 
void shift(unsigned char *buf)
{
   for(int i=0;i<7;i++)
   {
      buf[i]=buf[i+1];
   }
}

BFS scheint das Format von flatout zu sein. Zumindest ähnelt sich das Format von BFS aus Flatout2. Hier ein Repo zu einem Quelloffenen unpacker

MEMORY DUMP

Ansatz

Die entdeckte Perl-Datei(en) sollte(n) im Memory liegen.

Dump-Zeitpunkt

Prozesse sterben relativ schnell, wir müssen zum richtigen Zeitpunkt einen Memory Dump erstellen.

Ein Prozess „confd.plx“ übergibt per TCP über den Port 4472 dem Prozess „backup.plx“ auf Nachfrage Konfigurationen. Hier sollte der Perl-Code bereits entpackt sein.

killall -r confd && nc -l 4472

Die Kommunikation mit „confd.plx“ lässt sich so ersetzen. Das Timeout auf eine Antwort ist hier sehr lange.