-
-
[原创]CTF2018第七题分析(qwertyaa)
-
发表于: 2018-6-28 19:58 3307
-
0x0,0x1,0x2
0x3,0x4,0x0
0x5,0x6,0x0
0x5,0x7,0x1
0x4,0x6,0x1
0x8,0x2,0x3
0x9,0x2,0x4
0x7,0xa,0x3
0x8,0xc,0x5
0xb,0xd,0x6
0xc,0xd,0x7
0xb,0xe,0x9
0xe,0x8,0xa
0xf,0x9,0xa
0xf,0xb,0xc
0xf,0xd,0xe
f_y,z(x)=box2[x][y][z]
f_x,z(y)=box2[x][y][z]
f_x,y(z)=box2[x][y][z]
y[i]=box2[x[p[i][0]]][x[p[i][1]]][x[p[i][2]]]
y[i]=box2[x[p[i][0]]][x[p[i][1]]][x[p[i][2]]],i=0,1,2...15
这样我们先预处理出p和p中的依赖关系表和“知2求1”的过程:
逆向部分
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> using namespace std; void doPause(){ #ifdef linux printf("Press enter to exit."); fflush(stdout); system("read unusedVar"); #else system("pause"); #endif } typedef unsigned char uchar; typedef unsigned int uint; uchar key[16]={0x14,0x22,0x1E,0x10,0x38,0x30,0x18,0x10,0x4,0x1A,0x24,0x8,0x2,0x26,0x38,0x2A}; char trans[]="abcdefghijklmnopqrstuvwxyz+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; char input[20]; uchar box1[16][16],box2[64][64][64]; void judge(){ uchar box[22][16]; for(int i=0;i<16;i++){ int j=0; while(j<64&&trans[j]!=input[i])j++; if(j>=64) { puts("input error"); doPause(); exit(-1); } box[0][i]=j; } puts(""); for(int i=0;i<20;i++){ for(int j=0;j<16;j++){ int a[3]={0},p=0; for(int k=0;k<16;k++){ int l=(k+j)%16; if(box1[j][l]) a[p++]=box[i][l]; } box[i+1][j]=box2[a[0]][a[1]][a[2]]; } } for(int i=0;i<16;i++)if(key[i]!=box[19][i]){ puts("serial error"); return; } for(int i=0;i<16;i++)printf("%c",trans[box[9][i]>>1]); puts(""); } void readFile(const char*fn,void*buf){ FILE*f=fopen(fn,"rb"); fseek(f,0,SEEK_END); uint size=ftell(f); fseek(f,0,SEEK_SET); fread(buf,size,1,f); fclose(f); } int main(){ readFile("dump.hex",box1); readFile("dump2.hex",box2); puts("Only 'a'-'z','A'-'Z','0'-'9' accepted."); puts("Only 16 chars accepted."); printf("Serial:"); scanf("%17s",input); if(strlen(input)>16)input[0]=0;//ployfill for scanf_s judge(); doPause(); return 0; }
auto fp, begin, end, i; fp = fopen("dump2.hex", "wb"); begin = 0x139FEF0; end = begin+64*64*64; for ( i = begin; i < end; i ++ ) fputc(Byte(i), fp); fclose(fp);
分析部分
0x0,0x1,0x2
0x3,0x4,0x0
0x5,0x6,0x0
0x5,0x7,0x1
0x4,0x6,0x1
0x8,0x2,0x3
0x9,0x2,0x4
0x7,0xa,0x3
0x8,0xc,0x5
0xb,0xd,0x6
0xc,0xd,0x7
0xb,0xe,0x9
0xe,0x8,0xa
0xf,0x9,0xa
0xf,0xb,0xc
0xf,0xd,0xe
f_y,z(x)=box2[x][y][z]
f_x,z(y)=box2[x][y][z]
f_x,y(z)=box2[x][y][z]
y[i]=box2[x[p[i][0]]][x[p[i][1]]][x[p[i][2]]]
y[i]=box2[x[p[i][0]]][x[p[i][1]]][x[p[i][2]]],i=0,1,2...15
这样我们先预处理出p和p中的依赖关系表和“知2求1”的过程:
//p和p中的依赖关系 int p[16][3]; int rp[16][4]={0}; for(int j=0;j<16;j++){ int q=0; for(int k=0;k<16;k++){ int l=(k+j)%16; if(box1[j][l]) p[j][q++]=l,rp[l][rp[l][3]++]=j; } } //“知2求1”的过程 uchar rbox1[64][64][64],rbox2[64][64][64],rbox3[64][64][64]; for(int i=0;i<64;i++){ for(int j=0;j<64;j++){ for(int k=0;k<64;k++)rbox1[box2[i][j][k]][j][k]=i; } } for(int i=0;i<64;i++){ for(int j=0;j<64;j++){ for(int k=0;k<64;k++)rbox2[i][box2[i][j][k]][k]=j; } } for(int i=0;i<64;i++){ for(int j=0;j<64;j++){ for(int k=0;k<64;k++)rbox3[i][j][box2[i][j][k]]=k; } }
uchar rbox1[64][64][64],rbox2[64][64][64],rbox3[64][64][64]; int p[16][3]; int rp[16][4]={0}; bool test(uchar x,uchar y,uchar z,uchar key[16],uchar res[16]){ const int A=0,B=1,C=3; res[A]=x; res[B]=y; res[C]=z; uchar d[16]; for(int i=0;i<16;i++)d[i]=3; bool vt[16]={0}; vt[A]=vt[B]=vt[C]=1; for(int z=0;z<3;z++)d[rp[A][z]]--; int q[20]={A,B,C}; int f=0,l=2; while(f<l){ f++; for(int z=0;z<3;z++){ int v=rp[q[f]][z]; d[v]--; if(d[v]<=1){ l++; int a0=p[v][0]; int a1=p[v][1]; int a2=p[v][2]; int k=key[v]; if(!vt[a0]){ res[a0]=rbox1[k][res[a1]][res[a2]]; vt[a0]=1; q[l]=a0; }else if(!vt[a1]){ res[a1]=rbox2[res[a0]][k][res[a2]]; vt[a1]=1; q[l]=a1; }else if(!vt[a2]){ res[a2]=rbox3[res[a0]][res[a1]][k]; vt[a2]=1; q[l]=a2; }else{ if(k!=box2[res[a0]][res[a1]][res[a2]])return false; l--; } } } } return l==15; } void rev(uchar key[16],uchar res[16]){ int cnt=0; for(int i=0;i<64;i++){ for(int j=0;j<64;j++){ for(int k=0;k<64;k++){ if(test(i,j,k,key,res))return; } } } }
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> using namespace std; typedef unsigned char uchar; typedef unsigned int uint; uchar key[16]={0x14,0x22,0x1E,0x10,0x38,0x30,0x18,0x10,0x4,0x1A,0x24,0x8,0x2,0x26,0x38,0x2A}; char trans[]="abcdefghijklmnopqrstuvwxyz+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; char input[20]; uchar box1[16][16],box2[64][64][64],rbox1[64][64][64],rbox2[64][64][64],rbox3[64][64][64]; void judge(){ uchar box[22][16]; for(int i=0;i<16;i++){ int j=0; while(j<64&&trans[j]!=input[i])j++; box[0][i]=j; } for(int i=0;i<20;i++){ for(int j=0;j<16;j++){ int a[3]={0},p=0; for(int k=0;k<16;k++){ int l=(k+j)%16; if(box1[j][l]) a[p++]=box[i][l]; } box[i+1][j]=box2[a[0]][a[1]][a[2]]; } } for(int k=0;k<=19;k++){ for(int i=0;i<16;i++)printf("%02x ",box[k][i]); puts(""); } for(int i=0;i<16;i++)if(key[i]!=box[19][i])puts("serial error"); for(int i=0;i<16;i++)printf("%c",trans[box[9][i]>>1]); puts(""); } void readFile(const char*fn,void*buf){ FILE*f=fopen(fn,"rb"); fseek(f,0,SEEK_END); uint size=ftell(f); fseek(f,0,SEEK_SET); fread(buf,size,1,f); fclose(f); } int p[16][3]; int rp[16][4]={0}; bool test(uchar x,uchar y,uchar z,uchar key[16],uchar res[16]){ const int A=0,B=1,C=3; res[A]=x; res[B]=y; res[C]=z; uchar d[16]; for(int i=0;i<16;i++)d[i]=3; bool vt[16]={0}; vt[A]=vt[B]=vt[C]=1; for(int z=0;z<3;z++)d[rp[A][z]]--; int q[20]={A,B,C}; int f=0,l=2; while(f<l){ f++; for(int z=0;z<3;z++){ int v=rp[q[f]][z]; d[v]--; if(d[v]<=1){ l++; int a0=p[v][0]; int a1=p[v][1]; int a2=p[v][2]; int k=key[v]; if(!vt[a0]){ res[a0]=rbox1[k][res[a1]][res[a2]]; vt[a0]=1; q[l]=a0; }else if(!vt[a1]){ res[a1]=rbox2[res[a0]][k][res[a2]]; vt[a1]=1; q[l]=a1; }else if(!vt[a2]){ res[a2]=rbox3[res[a0]][res[a1]][k]; vt[a2]=1; q[l]=a2; }else{ if(k!=box2[res[a0]][res[a1]][res[a2]])return false; l--; } } } } return l==15; } void rev(uchar key[16],uchar res[16]){ int cnt=0; for(int i=0;i<64;i++){ for(int j=0;j<64;j++){ for(int k=0;k<64;k++){ if(test(i,j,k,key,res))return; } } } } void runOnce(uchar key[16]){ for(int j=0;j<16;j++){ int a[3]={0},p=0; for(int k=0;k<16;k++){ int l=(k+j)%16; if(box1[j][l]) a[p++]=key[l]; } printf("%02x ",box2[a[0]][a[1]][a[2]]); } puts(""); } int main(){ readFile("dump.hex",box1); readFile("dump2.hex",box2); for(int j=0;j<16;j++){ int q=0; for(int k=0;k<16;k++){ int l=(k+j)%16; if(box1[j][l]) p[j][q++]=l,rp[l][rp[l][3]++]=j; } } for(int i=0;i<64;i++){ for(int j=0;j<64;j++){ for(int k=0;k<64;k++)rbox1[box2[i][j][k]][j][k]=i; } } for(int i=0;i<64;i++){ for(int j=0;j<64;j++){ for(int k=0;k<64;k++)rbox2[i][box2[i][j][k]][k]=j; } } for(int i=0;i<64;i++){ for(int j=0;j<64;j++){ for(int k=0;k<64;k++)rbox3[i][j][box2[i][j][k]]=k; } } uchar res[22][16]; memcpy(res[19],key,sizeof key); for(int i=19;i>0;i--){ for(int j=0;j<16;j++)printf("%02x ",res[i][j]);puts("..."); rev(res[i],res[i-1]); for(int j=0;j<16;j++)printf("%02x ",res[i-1][j]);puts(""); runOnce(res[i-1]); } char flag[17];flag[16]=0; for(int i=0;i<16;i++){ flag[i]=trans[res[0][i]]; } puts(flag); strcpy(input,flag); judge(); return 0; }
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> using namespace std; void doPause(){ #ifdef linux printf("Press enter to exit."); fflush(stdout); system("read unusedVar"); #else system("pause"); #endif } typedef unsigned char uchar; typedef unsigned int uint; uchar key[16]={0x14,0x22,0x1E,0x10,0x38,0x30,0x18,0x10,0x4,0x1A,0x24,0x8,0x2,0x26,0x38,0x2A}; char trans[]="abcdefghijklmnopqrstuvwxyz+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; char input[20]; uchar box1[16][16],box2[64][64][64]; void judge(){ uchar box[22][16]; for(int i=0;i<16;i++){ int j=0; while(j<64&&trans[j]!=input[i])j++; if(j>=64) { puts("input error"); doPause(); exit(-1); } box[0][i]=j; } puts(""); for(int i=0;i<20;i++){ for(int j=0;j<16;j++){ int a[3]={0},p=0; for(int k=0;k<16;k++){ int l=(k+j)%16; if(box1[j][l]) a[p++]=box[i][l]; } box[i+1][j]=box2[a[0]][a[1]][a[2]]; } } for(int i=0;i<16;i++)if(key[i]!=box[19][i]){ puts("serial error"); return; } for(int i=0;i<16;i++)printf("%c",trans[box[9][i]>>1]); puts(""); } void readFile(const char*fn,void*buf){ FILE*f=fopen(fn,"rb"); fseek(f,0,SEEK_END); uint size=ftell(f); fseek(f,0,SEEK_SET); fread(buf,size,1,f); fclose(f); } int main(){ readFile("dump.hex",box1); readFile("dump2.hex",box2); puts("Only 'a'-'z','A'-'Z','0'-'9' accepted."); puts("Only 16 chars accepted."); printf("Serial:"); scanf("%17s",input); if(strlen(input)>16)input[0]=0;//ployfill for scanf_s judge(); doPause(); return 0; }
#include <iostream> #include <cstdio> #include <cstring> #include <cstdlib> using namespace std; void doPause(){ #ifdef linux printf("Press enter to exit."); fflush(stdout); system("read unusedVar"); #else system("pause"); #endif } typedef unsigned char uchar; typedef unsigned int uint; uchar key[16]={0x14,0x22,0x1E,0x10,0x38,0x30,0x18,0x10,0x4,0x1A,0x24,0x8,0x2,0x26,0x38,0x2A}; char trans[]="abcdefghijklmnopqrstuvwxyz+-ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; char input[20]; uchar box1[16][16],box2[64][64][64]; void judge(){ uchar box[22][16]; for(int i=0;i<16;i++){ int j=0; while(j<64&&trans[j]!=input[i])j++; if(j>=64) { puts("input error"); doPause(); exit(-1); } box[0][i]=j; } puts(""); for(int i=0;i<20;i++){ for(int j=0;j<16;j++){ int a[3]={0},p=0; for(int k=0;k<16;k++){ int l=(k+j)%16; if(box1[j][l]) a[p++]=box[i][l]; } box[i+1][j]=box2[a[0]][a[1]][a[2]]; } } for(int i=0;i<16;i++)if(key[i]!=box[19][i]){ puts("serial error"); return; } for(int i=0;i<16;i++)printf("%c",trans[box[9][i]>>1]); puts(""); } void readFile(const char*fn,void*buf){ FILE*f=fopen(fn,"rb"); fseek(f,0,SEEK_END); uint size=ftell(f); fseek(f,0,SEEK_SET); fread(buf,size,1,f); fclose(f); } int main(){ readFile("dump.hex",box1); readFile("dump2.hex",box2); puts("Only 'a'-'z','A'-'Z','0'-'9' accepted."); puts("Only 16 chars accepted."); printf("Serial:"); scanf("%17s",input); if(strlen(input)>16)input[0]=0;//ployfill for scanf_s judge(); doPause(); return 0; }