- 知识点:
1,基本算法;
2,ida 的使用;
0x01
下载题目,一个没有后缀的文件,直接拖入 exeinfoPE查壳:
ELF linux文件, 64位;
0x02
拖入 ida, 静态分析,shift + F12,查看字符串 ,找到主函数 main, F5反编译一波:
主要代码段以及分析:
void __fastcall __noreturn main(__int64 a1, char **a2, char **a3)
{
size_t v3; // rsi@1
int i; // [sp+3Ch] [bp-54h]@3
char s[36]; // [sp+40h] [bp-50h]@1 定义一个长度36数组
int v6; // [sp+64h] [bp-2Ch]@1 整型变量 v6
__int64 v7; // [sp+68h] [bp-28h]@1 定义一个长整型变量
char v8[8]; // [sp+70h] [bp-20h]@1 定义一个长度8数组,这里存在反编译错误;
int v9; // [sp+8Ch] [bp-4h]@1 定义一个整型变量
v9 = 0;
strcpy(v8, ":\"AL_RT^L*.?+6/46"); //strcpy()复制 16 位字符串给 v8,v8长度位 8,显然放不下的,所以是反编译错误了;
v6 = 7;
v7 = 'ebmarah'; //小端存储,需要逆序字符串
printf("Welcome to the RC3 secure password guesser.\n", a2, a3);
printf("To continue, you must enter the correct password.\n");
printf("Enter your guess: ");
__isoc99_scanf("%32s", s); //输入入口
v3 = strlen(s);
if ( v3 < strlen(v8) ) //strlen() v8与输入的字符串做对比
sub_4007C0(); //输出 incrrect password!
for ( i = 0; i < strlen(s); ++i )
{
if ( i >= strlen(v8) )
sub_4007C0(); // 输出:incrrect password!
if ( s[i] != (char)(*((_BYTE *)&v7 + i % v6) ^ v8[i]) ) // (char)强制类型转换 ; __BYTE unsigned char类型
sub_4007C0();
}
sub_4007F0(); //输出 password
}
/*代码逻辑:
第一个 if, 检测用户输入长度 ,如果长度 < strlen(v8) ,直接 exit;
for, 做 strlen(s) 次循环;
第二个 if, 检测 i 的值,如果 i > strlen(v8) ,实际上还是检测输入的 s 长度;
第三个 if, (char) 强制类型转换 *(__BYTE *)&v7 --> 一个指向 v7[0] 的指针,*(__BYTE *)&v7 + i % v6 --> 做指针加运算,指针向后移动,
实际上就相当于顺序读取 v7 数组里的元素; s[i] != (...) --> 将用户输入与 v7数组元素分别与 v8数组元素做 ^ 运算的字符比较,相等则跳到 sub_400ef0() ,跳出 password;
*/
0x03
明白代码逻辑,直接 py:
v7 = "harambe";
v8 = ":\"AL_RT^L*.?+6/46";
flag = "";
for i in range(len(v8)):
flag += chr(ord(v7[i%7]) ^ ord(v8[i]));
print(flag)
#RC3-2016-XORISGUD