These pages are written by only Japanese.
|
Namazu for hns による簡易全文検索です。 詳細は 詳細指定/ヘルプをご参照下さい。 |
|||||||||||||||||||||||||||||||||||||||||||||||
php swfdump.phps 5791.swf <略> [12397] tag=DefineBitsLossless2(36) length=9938 image_id=1136 format=5 width=160 height=160 argb bitmap exists <略> [12748] tag=DefineBitsLossless2(36) length=2471 image_id=1196 format=5 width=80 height=80 argb bitmap exists <略>
mkdir -p ~/public_html/diary/data/2008/07/11/swfed cp config.m4 swfed.c php_swfed.h \ swf_*.? jpeg_segment.? bitstream.? swf*.phps \ ~/public_html/diary/data/2008/07/11/swfed/.
libpng にある入出力はpng_read() や png_write() を通して処理されます。 現行では fread() や fwrite() を呼ぶだけです。FILE * は png_struct 内部に記憶され、png_init_io() を経由して初期化されます。 I/O 命令を変更したいなら、png_init_io() を呼ぶ代わりに実行時に png_set_read_fn() と png_set_write_fn() 関数を通してライブラリ指定 のコールバックを設定することができます。という事ですが、
png_set_read_fn(png_structp read_ptr, voidp read_io_ptr, png_rw_ptr read_data_fn) png_set_write_fn(png_structp write_ptr, voidp write_io_ptr, png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn); voidp read_io_ptr = png_get_io_ptr(read_ptr); voidp write_io_ptr = png_get_io_ptr(write_ptr); void user_read_data(png_structp png_ptr, png_bytep data, png_size_t length); void user_write_data(png_structp png_ptr, png_bytep data, png_size_t length); void user_flush_data(png_structp png_ptr);API群を見てもいまいちピンと来ないので、 「png_set_write_fn」で検索したところ以下のページを発見。
png_get_io_ptrによって、png_set_read_fun/png_set_write_funで与えた引数を png_ptrで示されるコンテキストオブジェクトから取得できるので、それを ストリームへのポインタにキャストして仕事をまっとうしているわけです。あー。なるほど。
static void png_default_write_data(png_structp png_ptr,png_bytep data,png_size_ t length) { OSErr err; long llong=length; short refNum=((MyPNGFileRec *)png_ptr->io_ptr)->refNum; err=FSWrite(refNum,&llong,data); if (err!=noErr) { png_error(png_ptr,"Write Error"); } }なるほど。なるほど。
typedef struct my_png_buffer_ { unsigned char *data; unsigned long data_len; unsigned long data_offset; } my_png_buffer; void png_memread_func(png_structp png_ptr, png_bytep buf, png_size_t size){ my_png_buffer *png_buff = (my_png_buffer *)png_get_io_ptr(png_ptr); if (png_buff->data_offset + size <= png_buff->data_len) { memcpy(buf, png_buff->data + png_buff->data_offset, size); png_buff->data_offset += size; } else { png_error(png_ptr,"png_mem_read_func failed"); } } void png_data_read(png_structp png_ptr, my_png_buffer *png_buff) { png_set_read_fn(png_ptr, (png_voidp) png_buff, (png_rw_ptr)png_memread_func); }こんな感じでいいかな。
% ./a.out cyan_3x3.PNG png_filename=cyan_3x3.PNG png_buff.data_len=152 (width, height)=(3,3) bpp=8 color_type=2異常なファイル1 (バッファオーバーフロウ)
% ./a.out cyan_3x3-cut.PNG png_filename=cyan_3x2-cut.PNG png_buff.data_len=91 libpng error: png_mem_read_func failed アボートしましたファイルの後ろを少し削ったファイルを渡したところ、 長さチェックで弾いてくれました。よしっ。
% ./a.out pngtest.png png_filename=pngtest.png png_buff.data_len=8574 libpng error: PNG unsigned integer out of range. アボートしましたふむ。完璧。
# du -sk * <略> 3724 php-pear 2402880 yum/var/cache/yum が多すぎるので /awm/yum_cache を作って、そこに退避。
image_data = (png_bytepp) malloc(png_height * sizeof(png_bytep)); for (y=0; y < png_height; y++) { image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, info_ptr)); } png_read_image(png_ptr, image_data); for (y=0; y < png_height; y++) { printf("y=%lu: ", y); for (x=0; x < png_width; x++) { printf("%02x%02x%02x ", image_data[y][3*x], image_data[y][3*x+1], image_data[y][3*x+2]); } printf("\n"); }
% ./png_dump cyan_3x3.PNG png_filename=cyan_3x3.PNG png_buff.data_len=152 (width, height)=(3,3) bpp=8 color_type=2 y=0: 00ffff 00ffff 00ffff y=1: 00ffff 00ffff 00ffff y=2: 00ffff 00ffff 00ffff %
% php swfdump.phps 5791.swf <略> [12397] tag=DefineBitsLossless2(36) length=9938 image_id=1136 format=5 width=160 height=160 argb bitmap existsimage_id 1136 の画像を見つけたので、それを入れ替えてみます。
% php swfreplacepngdata.phps 5791.swf 1136 cyan_3x3.PNG > tmp.swfさて、dump して確認。
% php swfdump.phps 5791.swf <略> [12397] tag=DefineBitsLossless(20) length=22 image_id=1136 format=5 width=3 height=3 xrgb bitmap exists入れ替わりました… ( ̄― ̄)
typedef struct my_png_buffer_ { unsigned char *data; unsigned long data_len; unsigned long data_offset; } my_png_buffer; void png_data_write_func(png_structp png_ptr, png_bytep buf, png_size_t size){ my_png_buffer *png_buff = (my_png_buffer *)png_get_io_ptr(png_ptr); unsigned long new_data_len; if (png_buff->data_offset + size > png_buff->data_len) { new_data_len = 2 * png_buff->data_len; if (png_buff->data_offset + size > new_data_len) { new_data_len = png_buff->data_offset + size; } png_buff->data = realloc(png_buff->data, new_data_len); if (png_buff->data == NULL) { fprintf(stderr, "can't realloc: new_data_len(%lu), data_len(%lu)\n", new_data_len, png_buff->data_len); png_error(png_ptr,"png_data_write_func failed"); } png_buff->data_len = new_data_len; } memcpy(png_buff->data + png_buff->data_offset, buf, size); png_buff->data_offset += size; } void png_data_write(png_structp png_ptr, my_png_buffer *png_buff) { png_set_write_fn(png_ptr, (png_voidp) png_buff, (png_rw_ptr)png_data_write_func, NULL); } /* ... */ my_png_buffer png_buff; png_buff.data = NULL; png_buff.data_len = 0; png_buff.data_offset = 0; png_data_write(png_ptr, &png_buff); png_write_info(png_ptr, info_ptr); png_write_image(png_ptr, image_data); png_write_end(png_ptr, info_ptr);
% ./a.out foo.png png_filename=foo.png (width, height)=(3,3) bpp=8 color_type=2 png_buff.(data=0x8b9ebf8,data_len=128,data_offset=96) % % ./png_dump foo.png png_filename=foo.png png_buff.data_len=96 (width, height)=(3,3) bpp=8 color_type=2 y=0: 102030 102030 102030 y=1: 102030 102030 102030 y=2: 102030 102030 102030出来たー。(*'ω'*)