图显示不出来吗。
分析如上图:
[C] 纯文本查看 复制代码 if ( v3 < strlen(v8) )
quit();
这里可以判定输入字符串长度>=strlen(v8);
[C] 纯文本查看 复制代码 if ( i >= strlen(v8) )
quit();
这样的话就可以最终确定:strlen(input_string)==strlen(v8),确定了input_string的长度为17。
既然 [C] 纯文本查看 复制代码 input_string[i] != (char)(*((_BYTE *)&v7 + i % v6) ^ v8[i])
就判断是错误,说明每一个输入的字符都需要跟后面算出来的结果相比对,对比成功才能得到
[C] 纯文本查看 复制代码 printf("You entered the correct password!\nGreat job!\n"); 。
所以想要得到正确的输入,通过对比的内容(像面镜子)就可以得到了。
那我们就看看这个对比度内容是什么:
[C] 纯文本查看 复制代码 (char)(*((_BYTE *)&v7 + i % v6) ^ v8[i])
咱们先看看里面的参数:
- v6=7;
- v8=“:\"AL_RT^L*.?+6/46”;
- v7
咱们一起来看看v7:类型是_int64,v7保存的数据是28537194573619560LL,证明这是一个long long int类型的数据。
int64的64可能是因为一个long long int数据占8byte=64bit的长度。(测算方法:[C] 纯文本查看 复制代码 printf("\n\n%d",sizeof(long long int));
//输出结果为8,即8byte )
但是上面需要的是char类型的(&v7+偏移量)来确定字符,并不需要int类型的数据,那么这是怎么回事呢?看下面的分析:
(*byte)==>(char *)类似于强制类型转换,&v7也就是将保存v7数据的地址提出,然后(_BYTE *)&v7可以用另一种更简单的方式理解:
[C] 纯文本查看 复制代码 char *target=(char *)&v7; 就是定义一个指针指向v7的首地址。
这样(指针+数字)的组合就是数组的索引方式,所以&v7+i==&v7(这部分是指针方面的知识)。
那么v7由int64转化到char类型后,(&v7+数字偏移量)索引到的应该是什么呢?这就不得不提到了数据在内存中存储的方式了:
long long int v7=28537194573619560,但是v7在内存中是以字节为单位存储的,把v7转化为16进制为:0x65626D61726168;
在内存中存储的方式是小端存储(little-endian),如图:
好像又没图了,不过我还能讲。接下来就是强制转化为字符形式,然后访问内部成员,数组需要从(首地址(即低地址)+偏移)来索引数据,所以索引出的(char *)v7="harambe";
明白了上面的指针和强制类型转化,小端序存储后,[C] 纯文本查看 复制代码 input_string[i] = (char)(*((_BYTE *)&v7 + i % v6) ^ v8[i]) 就很容易掌握了算法了,然后我们直接用c写两个程序把input_string字符串整理出来:
[C] 纯文本查看 复制代码 #include <stdio.h>
#include <string.h>
int main()
{
char v8[]=":\"AL_RT^L*.?+6/46";//strlen(v8)==strlen(input_string)
long long int v7=0x65626D61726168;
int i;
/*将long long int转化为字符类型
注意理解小端序存储方式和指针索引数据*/
char *target=(char *)&v7;
char final_string[20];
for(i=0;i<strlen(v8);i++)
{
final_string[i]=target[i%7]^v8[i];
printf("%c",final_string[i]);
}
return 0;
}
这样就可以得到flag为[C] 纯文本查看 复制代码 RC3-2016-XORISGUD ;
当然也可以这样做:
[C] 纯文本查看 复制代码 #include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
long long int v7=0x65626D61726168;
char a[]=":\"AL_RT^L*.?+6/46";
char input_string[20];
for(int i=0;i<strlen(a);i++)
{
input_string[i]=(char)(*((char *)&v7 + i%7)^a[i]);
printf("%c",input_string[i]);
}
printf("\n\n%d",sizeof(long long int));
return 0;
}
可以对比一下,哪些是可以相互替代的,更容易加深对指针和数组关系的理解。 |