CTF-Show 类型-7 WP
题目描述
flag格式为 ctfshow{明文}
094F5A0F0A0D1805103B0B3D143117183B720438350A45550967674D1E064F2969784440455A460F1A1B
TL;DR
本质上是思科路由器和安全设备的一种密码加密方式,由于可以被反向解密,已经被 deprecated 且不被推荐使用。
题解
解密 Link: - https://www.bejson.com/encrypt/type7_decode/ - http://web.chacuo.net/safeciscotype7 - http://www.atoolbox.net/Tool.php?Id=992
btw, insecure.org/sploits/cisco.passwords 处代码有误,我在 github.com/sfc9982/Cisco-Type-7-Password-Decoder 中修复了它,已向作者反馈。
有关思科的各种密码加密方案,可以参考 NSA 的文章 Cisco Password Types: Best Practices
给我们的启发就是生产环境中的加密方案也不一定安全
代码
cdecrypt()
中的迭代方式和数据类型的处理很啰嗦,有时间优化一下。
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
char xlat[] = "dsfd;kfoA,.iyewrkldJKDHSUBsgvca69834ncxv9873254k;fg87";
char pw_str1[] = " password 7 ";
char pw_str2[] = "enable password 7 ";
char pw_str3[] = "ip ftp password 7 ";
char pw_str4[] = " ip ospf message-digest-key 1 md5 7 ";
char *pname;
int cdecrypt(char *enc_pw, char *dec_pw)
{
unsigned int seed, i, val = 0;
if (strlen(enc_pw) & 1)
return -1;
seed = (enc_pw[0] - '0') * 10 + enc_pw[1] - '0';
if (seed > 15 || !isdigit(enc_pw[0]) || !isdigit(enc_pw[1]))
return -1;
for (i = 2; i <= strlen(enc_pw); i++)
{
if (i != 2 && !(i & 1))
{
dec_pw[i / 2 - 2] = val ^ xlat[seed++];
val = 0;
}
val *= 16;
if (isdigit(enc_pw[i] = toupper(enc_pw[i])))
{
val += enc_pw[i] - '0';
continue;
}
if (enc_pw[i] >= 'A' && enc_pw[i] <= 'F')
{
val += enc_pw[i] - 'A' + 10;
continue;
}
if (strlen(enc_pw) != i)
return -1;
}
dec_pw[++i / 2] = 0;
return 0;
}
int usage()
{
fprintf(stdout, "Usage: %s -p <encrypted password>\n", pname);
fprintf(stdout, " %s <router config file> <output file>\n", pname);
return 0;
}
int main(int argc, char **argv)
{
FILE *in = stdin, *out = stdout;
char line[257];
char passwd[65];
unsigned int i, pw_pos;
pname = argv[0];
if (argc > 1)
{
if (argc > 3)
{
usage();
exit(1);
}
if (argv[1][0] == '-')
{
switch (argv[1][1])
{
case 'h':
usage();
break;
case 'p':
memset(passwd, 0, sizeof(passwd));
if (cdecrypt(argv[2], passwd))
{
fprintf(stderr, "Error.\n");
exit(1);
}
fprintf(stdout, "password: %s\n", passwd);
break;
default:
fprintf(stderr, "%s: unknow option.", pname);
}
return 0;
}
if ((in = fopen(argv[1], "rt")) == NULL)
exit(1);
if (argc > 2)
if ((out = fopen(argv[2], "wt")) == NULL)
exit(1);
}
while (1)
{
for (i = 0; i < 256; i++)
{
if ((line[i] = fgetc(in)) == EOF)
{
if (i)
break;
fclose(in);
fclose(out);
return 0;
}
if (line[i] == '\r')
i--;
if (line[i] == '\n')
break;
}
pw_pos = 0;
line[i] = 0;
if (!strncmp(line, pw_str1, strlen(pw_str1)))
pw_pos = strlen(pw_str1);
if (!strncmp(line, pw_str2, strlen(pw_str2)))
pw_pos = strlen(pw_str2);
if (!strncmp(line, pw_str3, strlen(pw_str3)))
pw_pos = strlen(pw_str3);
if (!strncmp(line, pw_str4, strlen(pw_str4)))
pw_pos = strlen(pw_str4);
// if (!pw_pos)
// {
// fprintf(stdout, "%s\n", line);
// continue;
// }
memset(passwd, 0, sizeof(passwd));
if (cdecrypt(&line[pw_pos], passwd))
{
fprintf(stderr, "Error.\n");
exit(1);
}
else
{
if (pw_pos == strlen(pw_str1))
fprintf(out, "%s", pw_str1);
else if (pw_pos == strlen(pw_str2))
fprintf(out, "%s", pw_str2);
else if (pw_pos == strlen(pw_str3))
fprintf(out, "%s", pw_str3);
else if (pw_pos == strlen(pw_str4))
fprintf(out, "%s", pw_str4);
fprintf(out, "%s\n", passwd);
}
}
}