Images hardcoded in a source code [PHP interpreter]

Abstract

Recently I presented a simple way to protect an image against saving, today I will show how PHP interpreter protect some of its images against changing.

Image may be hardcoded in a regular array, where each field contains corresponding value of a byte in the original image file. You may imagine that you open image in a hex editor, you see its content as a chain of values of the bytes, and then you retype them as a fields in your array (this can be automatized of course).

Implementation

Mentioned array is located in main/logos.h:

#define CONTEXT_TYPE_IMAGE_GIF "Content-Type: image/gif"

static const unsigned char zend_logo[] = {
  71,  73,  70,  56,  57,  97, 113,   0,  72,   0, 
 213,   0,   0,  13,  13,  14,   1,   3,   6,   2, 
   5,   9,  46,  68,  94,  21,  29,  39,   5,  15, 


...

Above is used in main/php_logos.c:

int php_init_info_logos(void)
{
 if(zend_hash_init(&phpinfo_logo_hash, 0, NULL, NULL, 1)==FAILURE) 
  return FAILURE;

 php_register_info_logo(PHP_LOGO_GUID    , "image/gif", php_logo    , sizeof(php_logo));
 php_register_info_logo(PHP_EGG_LOGO_GUID, "image/gif", php_egg_logo, sizeof(php_egg_logo));
 php_register_info_logo(ZEND_LOGO_GUID   , "image/gif", zend_logo   , sizeof(zend_logo));

 return SUCCESS;
}

Above function is used in main/main.c:

int php_module_startup(sapi_module_struct *sf, zend_module_entry *additional_modules, uint num_additional_modules)
{

...

 /* initialize registry for images to be used in phpinfo() 
    (this uses configuration parameters from php.ini)
  */
 if (php_init_info_logos() == FAILURE) {
  php_printf("PHP:  Unable to initialize info phpinfo logos.\n");
  return FAILURE;
 }

...

Nothing interesting is here, so we will move back to php_init_info_logos. It uses php_register_info_logo implemented in main/php_logos.c:

PHPAPI int php_register_info_logo(char *logo_string, const char *mimetype, const unsigned char *data, int size)
{
 php_info_logo info_logo;

 info_logo.mimetype = mimetype;
 info_logo.mimelen  = strlen(mimetype);
 info_logo.data     = data;
 info_logo.size     = size;

 return zend_hash_add(&phpinfo_logo_hash, logo_string, strlen(logo_string), &info_logo, sizeof(php_info_logo), NULL);
}
body of php_info_logo is in the same file:
typedef struct _php_info_logo { 
 const char *mimetype;
 int mimelen;
 const unsigned char *data; 
 int size; 
} php_info_logo;

This structure will be useful, but take a look at the rest of the functions in this file:

#define CONTENT_TYPE_HEADER "Content-Type: "
int php_info_logos(const char *logo_string TSRMLS_DC)
{
 php_info_logo *logo_image;
 char *content_header;
 int len;

 if(FAILURE==zend_hash_find(&phpinfo_logo_hash, (char *) logo_string, strlen(logo_string), (void **)&logo_image))
  return 0;

 len = sizeof(CONTENT_TYPE_HEADER) - 1 + logo_image->mimelen;
 content_header = emalloc(len + 1);
 memcpy(content_header, CONTENT_TYPE_HEADER, sizeof(CONTENT_TYPE_HEADER) - 1);
 memcpy(content_header + sizeof(CONTENT_TYPE_HEADER) - 1 , logo_image->mimetype, logo_image->mimelen);
 content_header[len] = '\0';
 sapi_add_header(content_header, len, 0);

 PHPWRITE(logo_image->data, logo_image->size);
 return 1;
}

I extracted this code and made my own application that uses it to display this image. It uses its HTTP server (based on script created by Paul Buchheit). You may download sources by cloning git@github.com:RobertGawron/snippets.git (ImageAsTableInCSource directory). As visible, it works:

Images hardcoded in a source code [PHP interpreter]

07.03.2013, update: mentioned above images will be removed from the source code in PHP5.5

1 comment:

  1. Comments from my old blog:

    czarodziej, 8.04.2010 12:42
    Hej, też kiedyś myślałem o tym (hard-kodowaniu obrazków do binarki) jednak w zastosowaniach wbudowanych, np dla mikrokontrolerów ARM które obsługują jakieś wyświetlacze (np. od nokii), bo chyba tylko tutaj miałoby to sens, na komputerze to po co pchać obrazek do ramu, skoro z pliku jest dobrze? :)

    Co ja bym zrobił inaczej? Hm, tablice wypełniłbym danymi w systemie szesnastkowym. :P Ok, na serio to uważam za błąd pchanie tego do pliku .h, potem gdzieś ktoś przez nie uwagę załączy ten plik i dwa razy do ramu idzie ten sam obrazek. Lepiej jest wrzucić to do odrębnego pliku .c i zlinkować z programem.


    sokzzuka, 10.06.2010 13:48
    Pewnie dlatego, żeby nikt nie mógł ich podmienić np. tworząc własną dystrybucję. Poza tym są funkcje typu phpinfo(), które z nich korzystają.


    Robert, 10.06.2010 13:58
    Można je podmienić: trzeba napisać skrypt czytający obrazek, wypisać te dane, a później podmienić nimi oryginał i skompilować.


    sokzzuka, 18.06.2010 14:35
    no właśnie — skompilować co generalnie z tego co słyszałem nie jest zbyt banalne (ręczna kompilacja), a jak by to były zwykłe obrazki na dysku to by wystarczyło je podmienić :>


    Robert, 19.06.2010 12:04
    Zgadzam się z Tobą, że część osób z takim zabezpieczeniem sobie nie poradzi, jeśli tak postawić sprawę, to te obrazki mają sens.

    ReplyDelete