链接:http://www.shiyanbar.com/ctf/2004
下面是手动反汇编的源码,具体内容注释里已说明:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// arg_int_i must be 8 or 12
void judge(int arg_int_i)
{
int result; // rax
if (4 * (arg_int_i >> 2) != arg_int_i || 4 * (arg_int_i >> 4) == arg_int_i >> 2 || (!result) || arg_int_i >> 4)
{
puts("invalid username or password");
exit(0);
}
}
void judge_username_length(char *p_char_username)
{
int i; // [rsp+1Ch] [rbp-4h]
for (i = 0; i <= 49 && p_char_username[i]; ++i)
{
}
judge(i);
}
// so username_length must be 12
void judge_username(unsigned int *p_char_username)
{
long long username8_11; // [rsp+10h] [rbp-20h]
long long username4_7; // [rsp+18h] [rbp-18h]
long long username0_3; // [rsp+20h] [rbp-10h]
username0_3 = *p_char_username;
username4_7 = p_char_username[1];
username8_11 = p_char_username[2];
// username0_3 - username4_7 + username8_11 == 1550207830
// username4_7 + 3 * (username8_11 + username0_3) == 12465522610LL
// username8_11 * username4_7 == 3651346623716053780LL
// 这里可以自己解方程,我个人比较懒,用Python来计算
/*
#!/usr/bin/python3
from sympy import *
username0_3 = Symbol('username0_3')
username4_7 = Symbol('username4_7')
username8_11 = Symbol('username8_11')
print(solve(
[
username0_3 - username4_7 + username8_11 - 1550207830,
username4_7 + 3 * (username8_11 + username0_3) - 12465522610,
username8_11 * username4_7 - 3651346623716053780
],
[username0_3, username4_7, username8_11]
))
*/
// 结果:[(1635017059, 1953724780, 1868915551)]
// 也就是:0x61746163, 0x7473796c, 0x6f65635f
// 所以username 为 catalyst_ceo ,后面这个要做随机种子
if (username0_3 - username4_7 + username8_11 != 1550207830 || username4_7 + 3 * (username8_11 + username0_3) != 12465522610LL || (username8_11 * username4_7 != 3651346623716053780LL))
{
puts("invalid username or password");
exit(0);
}
}
// 不可以为大写字母
void judge_username_2(char *p_char_username)
{
int i; // [rsp+1Ch] [rbp-4h]
for (i = 0; p_char_username[i] != '\0'; ++i)
{
// 不可以为大写字母
if ((p_char_username[i] <= 96 || p_char_username[i] > 122) && p_char_username[i] != 95)
{
puts("invalid username or password");
exit(0);
}
}
}
void judge_password(int *p_int_username, int *p_int_password)
{
int i; // [rsp+2Ch] [rbp-14h]
char *p_char_password = (char *)p_int_password;
for (i = 0; p_char_password[i]; ++i)
{
// 对密码进行过滤
// 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
if ((p_char_password[i] <= 96 || p_char_password[i] > 122) && (p_char_password[i] <= 64 || p_char_password[i] > 90) && (p_char_password[i] <= 47 || p_char_password[i] > 57))
{
puts("invalid username or password");
exit(0);
}
}
srand(p_int_username[1] + p_int_username[0] + p_int_username[2]);
// 下面是十次随机数值:
// 0x00684749
// 0x673CE537
// 0x7B4505E7
// 0x70A0B262
// 0x33D5253C
// 0x515A7675
// 0x596D7D5D
// 0x7CD29049
// 0x59E72DB6
// 0x4654600D
// 下面是批量解密后的结果
// 0x56534C73
// sLSV
// 0x76345170
// pQ4v
// 0x4763334B
// K3cG
// 0x38577957
// WyW8
// 0x5A694136
// 6AiZ
// 0x77676768
// hggw
// 0x6A42484C
// LHBj
// 0x4339786D
// mx9C
// 0x56707352
// RspV
// 0x6A676747
// Gggj
// 所以密码为: sLSVpQ4vK3cGWyW86AiZhggwLHBjmx9CRspVGggj
if (p_int_password[0] - rand() != 1441465642)
{
puts("invalid username or password");
exit(0);
}
if (p_int_password[1] - rand() != 251096121)
{
puts("invalid username or password");
exit(0);
}
if (p_int_password[2] - rand() != -870437532)
{
puts("invalid username or password");
exit(0);
}
if (p_int_password[3] - rand() != -944322827)
{
puts("invalid username or password");
exit(0);
}
if (p_int_password[4] - rand() != 647240698)
{
puts("invalid username or password");
exit(0);
}
if (p_int_password[5] - rand() != 638382323)
{
puts("invalid username or password");
exit(0);
}
if (p_int_password[6] - rand() != 282381039)
{
puts("invalid username or password");
exit(0);
}
if (p_int_password[7] - rand() != -966334428)
{
puts("invalid username or password");
exit(0);
}
if (p_int_password[8] - rand() != -58112612)
{
puts("invalid username or password");
exit(0);
}
if (p_int_password[9] - rand() != 605226810)
{
puts("invalid username or password");
exit(0);
}
}
void flag_print(char *p_char_username, char *p_char_password)
{
int i; // [rsp+1Ch] [rbp-14h]
char str[] = {0x42, 0x13, 0x27, 0x62, 0x41, 0x35, 0x6B, 0x0F, 0x7B, 0x46, 0x3C, 0x3E, 0x67, 0x0C, 0x08, 0x59, 0x44, 0x72, 0x36, 0x05, 0x0F, 0x15, 0x54, 0x43, 0x38, 0x17, 0x1D, 0x18, 0x08, 0x0E, 0x5C, 0x31, 0x21, 0x16, 0x02, 0x09, 0x18, 0x14, 0x54, 0x59};
printf("your flag is: ALEXCTF{");
for (i = 0; i < strlen(p_char_password); ++i)
{
putchar(str[i] ^ p_char_password[i]);
}
puts("}");
}
int main()
{
char username[128] = {0};
char password[128] = {0};
// char *username="catalyst_ceo";
// char *password="sLSVpQ4vK3cGWyW86AiZhggwLHBjmx9CRspVGggj";
printf("Username: ");
scanf("%s", username);
printf("Password: ");
scanf("%s", password);
printf("Logging in");
judge_username_length(username);
judge_username((int *)username);
judge_username_2(username);
judge_password((int *)username, (int *)password);
flag_print(username, password);
}