読者です 読者をやめる 読者になる 読者になる

ichirin2501's diary

いっちりーん。

えんどれすZIP

http://d.hatena.ne.jp/ichirin2501/20100719/1279505134

前回のzipファイルと同じ仕組みを自動生成するプログラムを書こうとして挫折。


とりあえずr.zipのヘッダ部分をコピってくる。
違うファイル名で生成できるようにするためには、
Local file header: CRC32, FilenameLength, Filename
Central directory: CRC32, FilenameLength, Filename
End of central directory record:
Size of the central directory,
Offset of start of central directory with respect to the starting disk number,
zipfile comment length, zipfile comment


これらの値を変更するだけで恐らく動く…。
さっそく、書き始める。
案外だるい。
だるい。
ぎゃああああ、コピってきたバイナリが間違ってた。
ぎゃああああ、コードが長いし汚い。
よし、あとはCRC32を計算するコードをネットから拾って…
ん?自己ループさせる必要があるから…、
CRC32の値は探索しないとだめなことに今になって気付く
えーっと、0x00〜0xffだから、256か。あれ、256^4じゃね?…
あれれ、内部でCRC32の計算させるから恐ろしい計算量にorz
なんとか256^3まで計算量落とせないかと、考えたがだめでした。


英語に関してはスルーしてください。
変数名に関しても同様です(キリ

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <limits.h>
/*
code1 + namesize + code2 + filename + code3 +
code1 + namesize + code2 + filename + code4 + code3 + 
code1 + namesize + code2 + filename + code4 + code5 +
code6 + namesize + code7 + filename + 
code8 + centralsize + centralstartoffset + 
filesize
*/


unsigned char code1[] = {
  0x50,0x4b,0x03,0x04,0x14,0x00,0x00,0x00,0x08,0x00,0x08,0x03,0x64,0x3c,0xf9,0xf4,
  0x89,0x64,0x48,0x01,0x00,0x00,0xb8,0x01,0x00,0x00
};
unsigned char namesize[2];
unsigned char code2[] = { 0x00,0x00 };
unsigned char filename[(int)0xff];
unsigned char code3[] = {0x00,0x25,0x00,0xda,0xff};

unsigned char code4[] = { 0x00,0x2f,0x00,0xd0,0xff };
unsigned char code5[] = {
  0xc2,0x54,0x8e,0x57,0x39,0x00,0x05,0x00,0xfa,0xff,0xc2,0x54,0x8e,
  0x57,0x39,0x00,0x05,0x00,0xfa,0xff,0x00,0x05,0x00,0xfa,0xff,0x00,0x14,0x00,0xeb,
  0xff,0xc2,0x54,0x8e,0x57,0x39,0x00,0x05,0x00,0xfa,0xff,0x00,0x05,0x00,0xfa,0xff,
  0x00,0x14,0x00,0xeb,0xff,0x42,0x88,0x21,0xc4,0x00,0x00,0x14,0x00,0xeb,0xff,0x42,
  0x88,0x21,0xc4,0x00,0x00,0x14,0x00,0xeb,0xff,0x42,0x88,0x21,0xc4,0x00,0x00,0x14,
  0x00,0xeb,0xff,0x42,0x88,0x21,0xc4,0x00,0x00,0x14,0x00,0xeb,0xff,0x42,0x88,0x21,
  0xc4,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0xff,0xff,0x00,0x34,0x00,0xcb,
  0xff,0x42,0x88,0x21,0xc4,0x00,0x00,0x00,0x00,0xff,0xff,0x00,0x00,0x00,0xff,0xff,
  0x00,0x34,0x00,0xcb,0xff,0x42,0xe8,0x21,0x5e,0x0f,0x00,0x00,0x00,0xff,0xff,0x0a,
  0xf0,0x66,0x64,0x12,0x61,0xc0,0x15,0xdc,0xe8,0xa0,0x48,0xbf,0x48,0xaf,0x2a,0xb3,
  0x20,0xc0,0x9b,0x95,0x0d,0xc4,0x67,0x04,0x42,0x53,0x06,0x06,0x06,0x40,0x00,0x06,
  0x00,0xf9,0xff,0x6d,0x01,0x00,0x00,0x00,0x00,0x42,0xe8,0x21,0x5e,0x0f,0x00,0x00,
  0x00,0xff,0xff,0x0a,0xf0,0x66,0x64,0x12,0x61,0xc0,0x15,0xdc,0xe8,0xa0,0x48,0xbf,
  0x48,0xaf,0x2a,0xb3,0x20,0xc0,0x9b,0x95,0x0d,0xc4,0x67,0x04,0x42,0x53,0x06,0x06,
  0x06,0x40,0x00,0x06,0x00,0xf9,0xff,0x6d,0x01,0x00,0x00,0x00,0x00
};
unsigned char code6[] = {
  0x50,0x4b,0x01,
  0x02,0x14,0x00,0x14,0x00,0x00,0x00,0x08,0x00,0x08,0x03,0x64,0x3c,0xf9,0xf4,0x89,
  0x64,0x48,0x01,0x00,0x00,0xb8,0x01,0x00,0x00
};
unsigned char code7[] = {
  0x00,0x00,0x00,0x00,0x00,
  0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
};
unsigned char code8[] = {
  0x50,0x4b,0x05,0x06,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00
};
unsigned char centralsize[4];
unsigned char centralstartoffset[4];
unsigned char filesize[2];

#define CRCPOLY2 0xEDB88320UL

unsigned long crc2(size_t n, unsigned char *c){
  int i, j;
  unsigned long r;

  r = 0xFFFFFFFFUL;
  for (i = 0; i < n; i++) {
    r ^= c[i];
    for (j = 0; j < CHAR_BIT; j++)
      if (r & 1) r = (r >> 1) ^ CRCPOLY2;
      else       r >>= 1;
  }
  return r ^ 0xFFFFFFFFUL;
}

int main(int argc, char **v){
  FILE *fp;
  unsigned char buf[70000];
  char *p;
  char str[0xff] = {0};
  size_t size,i,nsz;

  if( argc<2 ){ printf("not file\n"); exit(1); }
  
  fp = fopen(v[1],"r");
  if( fp==NULL )                   { printf("not open file\n"); exit(1); }
  if( strlen(v[1])>(size_t)0xff/3 ){ printf("filename is too long\n"); exit(1); }  
  
  nsz = 0;
  //filename[0] = '_'; filename[1] = 0;
  if( (p = strrchr(v[1],'.'))!=NULL ){
    char *tmp = v[1];
    for(;tmp!=p;tmp++)nsz++;
    if( nsz==0 ){ printf("filename is not correct\n"); exit(1); }
    strcat(strncat(strcat(strncat(filename,v[1],nsz),"/"),v[1],nsz),".zip");
  }else{
    nsz = strlen(v[1]);
    strcat(strcat(strcat(strcat(filename,v[1]),"/"),v[1]),".zip");
  }
  //nsz = 1 + nsz + 2 + nsz + 4;
  nsz = nsz + 1 + nsz + 4;
  
  unsigned char *tmp = (unsigned char*)&nsz;
  namesize[0] = *tmp;
  namesize[1] = *(tmp+1);
  
  printf("%s = %02x %02x\n",filename,namesize[0],namesize[1]);
  
  
  int tt = sizeof(code1)*3 + sizeof(namesize)*3 + sizeof(code2)*3 + 
         nsz*3 + sizeof(code3)*2 + sizeof(code4)*2 + sizeof(code5);
  //printf("tt:%04x\n",tt);
  
  tmp = (unsigned char*)&tt;
  centralstartoffset[0] = *tmp;
  centralstartoffset[1] = *(tmp+1); 
  centralstartoffset[2] = *(tmp+2);
  centralstartoffset[3] = *(tmp+3);
  
  
  int zz = (tt+sizeof(code6)+sizeof(code7)+nsz+sizeof(namesize)) - tt;
  //printf("zz:%x\n",zz);
  
  tmp = (unsigned char*)&zz;
  centralsize[0] = *tmp;
  centralsize[1] = *(tmp+1);
  centralsize[2] = *(tmp+2);
  centralsize[3] = *(tmp+3);

  size = fread(buf,1,sizeof(buf),fp);
  if( size>(size_t)0xffff ){ printf("filesize is too long\n"); exit(1); }
  
  tmp = (unsigned char*)&size;
  filesize[0] = *tmp;
  filesize[1] = *(tmp+1);

  /*
code1 + namesize + code2 + filename + code3 +
code1 + namesize + code2 + filename + code4 + code3 + 
code1 + namesize + code2 + filename + code4 + code5 +
code6 + namesize + code7 + filename + 
code8 + centralsize + centralstartoffset + 
filesize
*/

  unsigned char ret[100000];
  int j;
  for(i=0; i<sizeof(code1); i++)      ret[i]   = code1[i];
  for(j=0; j<sizeof(namesize); j++)   ret[i++] = namesize[j];
  for(j=0; j<sizeof(code2); j++)      ret[i++] = code2[j];
  for(j=0; j<nsz; j++)                ret[i++] = filename[j];
  for(j=0; j<sizeof(code3); j++)      ret[i++] = code3[j];
  
  for(j=0; j<sizeof(code1); j++)      ret[i++] = code1[j];
  for(j=0; j<sizeof(namesize); j++)   ret[i++] = namesize[j];
  for(j=0; j<sizeof(code2); j++)      ret[i++] = code2[j];
  for(j=0; j<nsz; j++)                ret[i++] = filename[j];
  for(j=0; j<sizeof(code4); j++)      ret[i++] = code4[j];
  for(j=0; j<sizeof(code3); j++)      ret[i++] = code3[j];
  
  for(j=0; j<sizeof(code1); j++)      ret[i++] = code1[j];
  for(j=0; j<sizeof(namesize); j++)   ret[i++] = namesize[j];
  for(j=0; j<sizeof(code2); j++)      ret[i++] = code2[j];
  for(j=0; j<nsz; j++)                ret[i++] = filename[j];
  for(j=0; j<sizeof(code4); j++)      ret[i++] = code4[j];
  for(j=0; j<sizeof(code5); j++)      ret[i++] = code5[j];
  
  for(j=0; j<sizeof(code6); j++)      ret[i++] = code6[j];
  for(j=0; j<sizeof(namesize); j++)   ret[i++] = namesize[j];
  for(j=0; j<sizeof(code7); j++)      ret[i++] = code7[j];
  for(j=0; j<nsz; j++)                ret[i++] = filename[j];

  for(j=0; j<sizeof(code8); j++)      ret[i++] = code8[j];
  for(j=0; j<sizeof(centralsize); j++)ret[i++] = centralsize[j];
  for(j=0; j<sizeof(centralstartoffset); j++)ret[i++] = centralstartoffset[j];
  for(j=0; j<sizeof(filesize); j++)   ret[i++] = 0x00;
  
  
  unsigned char a,b,c,d,x;
  const unsigned char inf = 0xff;
  int flag = 0;
  for(a=0x00; a<inf; a++){
    for(b=0x00; b<inf; b++){
      for(c=0x00; c<inf; c++){
        for(d=0x00; d<inf; d++){
          unsigned char cr[] = {a,b,c,d};
          int g = 0;
          for(j=0; j<4; j++)ret[14+j] = cr[j];
          g += sizeof(code1)+sizeof(namesize)+sizeof(code2)+nsz+sizeof(code3);
          for(j=0; j<4; j++)ret[g+14+j] = cr[j];
          g += sizeof(code1)+sizeof(namesize)+sizeof(code2)+nsz+sizeof(code4)+sizeof(code3);
          for(j=0; j<4; j++)ret[g+14+j] = cr[j];
          g += sizeof(code1)+sizeof(namesize)+sizeof(code2)+nsz+sizeof(code4)+sizeof(code5);
          for(j=0; j<4; j++)ret[g+16+j] = cr[j];
          
          unsigned long data = crc2((size_t)i,ret);
          tmp = (unsigned char*)&data;
          //printf("%x %x %x %x\n",a,b,c,d);
          if( *tmp==a && *(tmp+1)==b && *(tmp+2)==c && *(tmp+3)==d ){
            flag = 1;
            goto YES;
          }
        }
      }
    }
  }
  YES:
  if( !flag ){ printf("Don't this name,sorry\n"); exit(1); }
  
  ret[i-2] = filesize[0];
  ret[i-1] = filesize[1];

  
  char uguu[0xff];
  char *e = v[1];
  //int k = 1;
  int k = 0;
  //uguu[0] = '_'; uguu[1]=0;
  for(; e!=p; e++)uguu[k++]=*e;
  uguu[k] = 0;
  strcat(uguu,".zip");
  printf("%s\n",uguu);
  
  
  FILE *fpw = fopen(uguu,"w");
  int __a,__b;
  __a = fwrite(ret,1,i,fpw);
  __b = fwrite(buf,1,size,fpw);
  printf("i:%d size:%d a:%d b:%d\n",i,size,__a,__b);
  
  
  fclose(fp);
  fclose(fpw);
  return 0;
}