步骤一:使用IDA PRO进行反汇编
首先,我们搜索main主函数,并使用F5反汇编得到以下代码:
void __fastcall __noreturn main(int a1, char **a2, char **a3)
{
size_t v3; // rsi // 用于存储字符串长度
int i; // [rsp+3Ch] [rbp-54h] // 循环计数器
char s[36]; // [rsp+40h] [rbp-50h] BYREF // 用户输入的字符串
int v6; // [rsp+64h] [rbp-2Ch] // 一个常量,值为7
__int64 v7; // [rsp+68h] [rbp-28h] // 一个常量,值为0x65626D61726168
char v8[28]; // [rsp+70h] [rbp-20h] BYREF // 一个常量字符串,值为":\"AL_RT^L*.?+6/46"
int v9; // [rsp+8Ch] [rbp-4h] // 一个变量,初始值为0
v9 = 0; // 设置v9为0
strcpy(v8, ":\"AL_RT^L*.?+6/46"); // 将常量字符串复制到v8
v7 = 0x65626D61726168LL; // 设置v7为常量值
v6 = 7; // 设置v6为7
printf("Welcome to the RC3 secure password guesser.\n"); // 打印欢迎信息
printf("To continue, you must enter the correct password.\n"); // 打印需要输入密码的提示
printf("Enter your guess: "); // 提示用户输入
__isoc99_scanf("%32s", s); // 读取用户输入的字符串,最多32个字符
v3 = strlen(s); // 计算用户输入的字符串长度
if ( v3 < strlen(v8) ) // 如果用户输入的字符串长度小于v8的长度
sub_4007C0(); // 则调用sub_4007C0函数
for ( i = 0; i < strlen(s); ++i ) // 对于用户输入的每一个字符
{
if ( i >= strlen(v8) ) // 如果当前字符的位置大于等于v8的长度
sub_4007C0(); // 则调用sub_4007C0函数
if ( s[i] != (char)(*((_BYTE *)&v7 + i % v6) ^ v8[i]) ) // 如果当前字符不等于v7的第(i%v6)个字节与v8的第i个字符的异或结果
sub_4007C0(); // 则调用sub_4007C0函数
}
sub_4007F0(); // 如果所有的字符都满足上述条件,则调用sub_4007F0函数
}
我们发现在判断里面调用了两个函数sub_4007C0 和sub_4007F0 ,同样反汇编之后得到:
void __noreturn sub_4007C0()
{
printf("Incorrect password!\n");
exit(0);
}
void __noreturn sub_4007F0()
{
printf("You entered the correct password!\nGreat job!\n");
exit(0);
}
这个循环的目的是检查输入的字符串是否满足某种条件,即输入的每个字符是否等于 v7 的某个字节和 v8 的对应字符的异或结果。如果输入的字符串的任何字符不满足这个条件,程序就会调用 sub_4007C0() 函数。
步骤二:处理字符串v7
v7 是一个64位整数,它被强制转换为字节指针,所以可以通过 *((_BYTE *)&v7 + i % v6) 来获取 v7 的某个字节。v6 是一个常数,值为7,所以 i % v6 会在0到6之间循环。
我们可以通过以下两种方法处理v7:
方法一: 通过脚本进行转换
hex_value = 0x65626D61726168
string_value = bytes.fromhex(hex(hex_value)[2:]).decode('utf-8')
print(string_value)
方法二: 直接在IDA中选中该字符串,按R进行转换,获字符串得:ebmarah
这里有一个非常重要的点:((_BYTE *)&v7 + i % v6) 即为 (char *)v7[i%v6] ,同时在CPU,x86都是小端序,但是IDA将之转换为了大端序。我们需要翻转字符得到harambe 。
步骤三:编写脚本
最后,我们使用Python3编写如下代码以获取flag:
v6 = 7
v7 = 'harambe'
v8 = ':\"AL_RT^L*.?+6/46'
flag = []
for i in range(len(v8)):
flag.append(chr(ord(v7[i % v6]) ^ ord(v8[i])))
print(''.join(flag))
最终我们获得flag:RC3-2016-XORISGUD
|