Reverse Engineering Stack Exchange is a question and answer site for researchers and developers who explore the principles of a system through analysis of its structure, function, and operation. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm dealing with a piece of malware that does extensive use of PCRE (Perl-compatible regular expressions). Normally I would be able to read them, but it seems they're in some kind of binary format (compiled, maybe?). They all start with ERCP (check out the hexdump below); FWIW, I strongly suspect the language that generated this code to be C++.

00000150  00 00 00 00 11 00 5e 00  00 00 01 00 00 00 45 52  |......^.......ER|
00000160  43 50 56 00 00 00 00 00  80 00 04 00 00 00 01 00  |CPV.............|
00000170  00 00 00 00 74 00 28 00  00 00 00 00 00 00 00 00  |....t.(.........|
00000180  00 00 00 00 00 00 5e 00  2a 5f 00 06 00 01 1a 54  |......^.*_.....T|
00000190  00 05 1c 2e 55 00 0b 1c  61 1c 61 1c 61 1c 61 1c  |....U...a.a.a.a.|
000001a0  61 1c 61 1c 61 1c 61 1c  2e 1c 6e 1c 65 1c 74 1b  |a.a.a.a...n.e.t.|
000001b0  55 00 2a 00 00 00 00 00  8d ff a5 95 0a 2d 2d 2d  |U.*..........---|

In this example, the regex seems to match some string related to an internet domain,

My question is: given a binary blob like this, is it possible to go back to a "human readable" (decompiled?) PCRE? (i.e. ^aaaaaa\.net$) If yes, how should I go about it ?

share|improve this question

Googling for 0x50435245 gives several hits, for example here:

/* Magic number to provide a small check against being handed junk. Also used
to detect whether a pattern was compiled on a host of different endianness. */

#define MAGIC_NUMBER  0x50435245UL   /* 'PCRE' */


/* The real format of the start of the pcre block; the index of names and the
code vector run on as long as necessary after the end. We store an explicit
offset to the name table so that if a regex is compiled on one host, saved, and
then run on another where the size of pointers is different, all might still
be well. For the case of compiled-on-4 and run-on-8, we include an extra
pointer that is always NULL. For future-proofing, a few dummy fields were
originally included - even though you can never get this planning right - but
there is only one left now.

Because people can now save and re-use compiled patterns, any additions to this
structure should be made at the end, and something earlier (e.g. a new
flag in the options or one of the dummy fields) should indicate that the new
fields are present. Currently PCRE always sets the dummy fields to zero.

typedef struct real_pcre {
  pcre_uint32 magic_number;
  pcre_uint32 size;               /* Total that was malloced */
  pcre_uint32 options;
  pcre_uint32 dummy1;             /* For future use, maybe */

  pcre_uint16 top_bracket;
  pcre_uint16 top_backref;
  pcre_uint16 first_byte;
  pcre_uint16 req_byte;
  pcre_uint16 name_table_offset;  /* Offset to name table that follows */
  pcre_uint16 name_entry_size;    /* Size of any name items */
  pcre_uint16 name_count;         /* Number of name items */
  pcre_uint16 ref_count;          /* Reference count */

  const unsigned char *tables;    /* Pointer to tables or NULL for std */
  const unsigned char *nullpad;   /* NULL padding */
} real_pcre;

Here's how it looks for your dump:

  dd 'PCRE'     ; magic_number
  dd 56h        ; size
  dd 800000h    ; options
  dd 4          ; dummy1
  dw 1          ; top_bracket
  dw 0          ; top_backref
  dw 0          ; first_byte
  dw 74h        ; req_byte
  dw 28h        ; name_table_offset
  dw 0          ; name_entry_size
  dw 0          ; name_count
  dw 0          ; ref_count
  dd 0          ; tables
  dd 0          ; nullpad

You will probably need to read the library source and/or try compiling some regexps with it to decode the rest.

share|improve this answer

That looks like a real_pcre structure, whose format is defined here among many other places online.

share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.