crackme文件
将crackme文件拷贝进seed虚拟机,运行,要求输出’Congratulations!'代表成功。
先用IDA打开,是基于英特尔386处理器的ELF文件:
找到main函数
其中主要的逻辑函数是sub_8048591():
加上注释的源代码:
int sub_8048591()
{
int i; // eax
_BOOL4 v1; // ebx
signed int v2; // esi
int v3; // edx
int v4; // eax
char v5; // cl
char v6; // di
int v7; // edx
int result; // eax
int v9; // [esp+18h] [ebp-8Ch]
char v10[124]; // [esp+28h] [ebp-7Ch]
dword_8049994("Password, please? ");
dword_8049990("%s", v10);
for ( i = 0; v10[i]; ++i ) // v10有多少个字符,i的值就是几
;
v1 = i == 19; // 如果i的值等于19,v1就赋值为1,否则为0
v2 = 10;
do
{
v3 = random() % 19; // 随机数字下标
v4 = 0;
v5 = byte_804869C[v3]; // 从自带的字符串byte_804869C中取一个字符给v5
v6 = v10[v3]; // 从输入的字符串v10中取一个字符给v6
v9 = v3 + 1;
v7 = 0;
while ( v7 < v9 ) // v7大小在0-v3
{
++v7;
v4 = 1828812941 * v4 + 12345; // v4的值相当于12345、1828812941 * v4 + 12345、………
}
if ( v5 != ((unsigned __int8)v6 ^ (unsigned __int8)v4) )// 要保证v5 == v6 ^ v4
v1 = 0; // 否则v1赋值为0
--v2;
}
while ( v2 );
if ( v1 ) // v1 == 1,就输出Congratulations!
result = dword_8049994("Congratulations!\n");
else // v1 == 0,就输出Oops..
result = dword_8049994("Oops..\n");
return result;
}
所以我们的目标就是不管随机数字下标v3 = random() % 19的值是多少,让v5 == v6 ^ v4恒成立,其实就是让下面三个数组的对应位置的值满足这个等式byte_804869C[i] == v10[i] ^ v4[i]:
自带的字节数组byte_804869C:
这是个字节数组,只是有些部分被IDA识别成了双字,右键单击byte_804869C->转换为未定义:
得到了20个字节的字节数组byte_804869C[20];
输入的字符串就是v10;
v4就是:v4 = 1828812941 * v4 + 12345;
所以我们可以逆向求出输入的字符串v10 == byte_804869C[20] ^ v4。
源代码:
flag.c
#include<stdio.h>
int main(){
int byte_804869C[20] = {0x6A,0xFB,0x4C,0x8D,0x58,0xF,0xD4,0xE8,0x94,0x98,0xEE,0x6B,0x18,0x030,0xE0,0x55,0xC5,0x28,0xE,0x90};
int v4 = 0;
int i;
char flag[19];
for(i = 0 ; i < 19 ; i++){
v4 = 1828812941 * v4 + 12345;
flag[i] = byte_804869C[i] ^ v4;
printf("%c",flag[i]);
}
return 0;
}
运行结果:
得到输入的字符串为:SesameOpenYourself!
把crackme文件拷贝进seed虚拟机,赋予可执行权限之后运行,输入字符串SesameOpenYourself!:
输出’Congratulations!'代表成功。