-
-
[原创]CTF2018第七题分析(qwertyaa)
-
发表于: 2018-6-28 19:58 3262
-
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”的过程:
逆向部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | #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; } |
1 2 3 4 5 6 | 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”的过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | //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; } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | 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 ; } } } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | #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; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | #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; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 | #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; } |
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课