BugCTF猪圈密码

一、简述

BugkuCTF 的猪圈密码题目,复盘一下,依旧 C 语言实现,万物终将归于 C。

题目地址:aHR0cHM6Ly9jdGYuYnVna3UuY29tL2NoYWxsZW5nZXMvZGV0YWlsL2lkLzE1OS5odG1s

二、思路概括

首先定义 2 个 3*3 的数组来分别存储两个井字格中分别对应的字母,然后再分别定义 2 个 2*2 的数组,来存储 x 格子中的 4 个英文字母,然后将特殊符号代表的英文字母组成一个数组,在控制台先输出图形对应的字母,然后输入对应的字母,将每个字符分别于定义的数组中的字母进行比较,如果相同,则就破解了密码。

三、解密原理

基于几何坐标的单表代换

不依靠复杂的算法,而是根据视觉位置的逻辑映射。

核心原理:空间位置 = 特定字母

猪圈密码将 26 个字母预先 "关" 在四个特定的 "猪圈" 中。解密的过程就是寻找符号边框所对应的空间坐标。

3.1 布局规则

井字布局
  1. 第一个井字格:存储 A-I。符号由外部边框组成(如 L 型、口 型、U 型)。
  2. 第二个井字格:存储 J-R。形状与第一组完全相同,但在内部增加一个 "点" 作为状态位(Flag),表示偏移量。
X 型布局(X-shape)
  1. 第一个 X 格:存储 S-V。符号由对角线形成的三角形组成。
  2. 第二个 X 格:存储 W-Z。形状相同,内部增加一个 "点"。

3.2 解密的三步逻辑

  1. 判断容器类型:观察符号是直角的(来自井字格)还是斜角的(来自 X 格)。
  2. 判断状态位(点) :观察符号内是否有 "点"。
    • 无点:对应第一组字母(A-I 或 S-V)。
    • 有点:对应第二组字母(J-R 或 W-Z)。
  3. 确定精确坐标:根据边框的开口方向,确定字母在格子的哪个位置(左上、正中、右下等)。

3.3 映射 (Bijection)

在数学上,这是一种单表代换密码

  • 定义域:26 个几何符号集合。
  • 值域:26 个英文字母集合。
  • 每一个符号 通过固定的查找表 对应唯一的字母。

3.4 为什么它容易被破解?

  1. 结构固定:标准猪圈密码的字母顺序通常是按 A-Z 排列的,这使得攻击者不需要密钥,只要识别出是猪圈密码就能解密。
  2. 频率特征保留:它没有改变字母出现的频率。如果密文中某个 "左开口" 符号出现次数最多,那它极大概率就是英语中最常出现的字母 E。

C 语言中,数组下标 [i][j] 实际上就是模拟了这个 "空间坐标"。

四、代码

cpp 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
//	定义第一个#数组
char j_zhujuan1[3][3] = {
'A','B','C',
'D','E','F',
'G','H','I',
};

//	定义第二个#数组 
char j_zhujuan2[3][3] = 
{
'J','K','L',
'M','N','O',
'P','Q','R',
};
//	定义第一个X数组
char x_zhujuan1[2][2] = {
'S','T',
'U','V',
};
//	定义第二个X数组
char x_zhujuan2[2][2] = {
'W','X',
'Y','Z',
};

    void printCipherKey() {
    int i, j;
    printf("============================================================\n");
    printf("        猪圈密码 (Pigpen Cipher)\n");
    printf("============================================================\n\n");

    printf("  [ 井字格 1: A-I ]           [ 井字格 2: J-R (带点 .) ]\n");
    for (i = 0; i < 3; i++) {
        printf("    %c | %c | %c ", j_zhujuan1[i][0], j_zhujuan1[i][1], j_zhujuan1[i][2]);
        
        printf("               ");
        
        printf("    %c. | %c. | %c.\n", j_zhujuan2[i][0], j_zhujuan2[i][1], j_zhujuan2[i][2]);

        if (i < 2) {
            printf("  ---+---+---           	 ---+---+---\n");
        }
    }

    printf("\n\n");

    printf("  [ X 型格 1: S-V ]           [ X 型格 2: W-Z (带点 .) ]\n");
    for (i = 0; i < 2; i++) {
        printf("      %c | %c ", x_zhujuan1[i][0], x_zhujuan1[i][1]);
        
        printf("                     ");
        
        printf("      %c. | %c.\n", x_zhujuan2[i][0], x_zhujuan2[i][1]);
        
        if (i < 1) {
            printf("     ---+---                   	       ---+---\n");
        }
    }

    printf("\n============================================================\n");
    printf("操作提示: 请对照上图符号形状,依次输入对应的字母完成解密。\n");
}

int main(){
char result[100];
char user_input[100];
int found = 0;
int count = 0;
int i,j,k,m,n,rs;
printCipherKey();
printf("\n请输入识别出的字符序列 (例:ABC...): ");
scanf("%s", user_input);

for(k=0;k<(int)strlen(user_input);k++){
	char target = toupper(user_input[k]);
	int found = 0;
		
        for (i = 0; i < 3; i++) {
            for (j = 0; j < 3; j++) {
                if (j_zhujuan1[i][j] == target || j_zhujuan2[i][j] == target) {
                    result[count++] = target;
                    found = 1;
                    break;
                }
            }
            if (found) break;
        }
        
        if(!found){
        	for(m=0;m<2;m++){
        		for(n=0;n<2;n++){
        			if (x_zhujuan1[m][n] == target || x_zhujuan2[m][n] == target) {
                    result[count++] = target;
                    found = 1;
                    break;
                }
			}
			if(found){
				 break;
			}
		}
	}
}
result[count] = '\0';
printf("\n[+] 解密成功!");
printf("\n[+] 原始字符串: %s", result);
    
printf("\n[+] 建议 Flag 格式: flag{");
for(rs=0; rs<count; rs++) printf("%c",tolower(result[rs]));
printf("}\n\n");
}
相关推荐
52Hz1181 小时前
力扣33.搜索旋转排序数组、153.寻找排序数组中的最小值
python·算法·leetcode
DeepModel1 小时前
【回归算法】高斯过程回归详解
算法·回归
古译汉书2 小时前
【IoT死磕系列】Day 3:学习HTTP!实战:STM32手写GET请求获取天气实战(附源码+八股文)
数据结构·stm32·物联网·网络协议·学习·算法·http
喜欢吃燃面2 小时前
基础算法:枚举(上)
c++·学习·算法
郝学胜-神的一滴2 小时前
计算思维:数字时代的超级能力
开发语言·数据结构·c++·人工智能·python·算法
m0_531237172 小时前
C语言-数组练习
c语言·开发语言·算法
识君啊2 小时前
Java 动态规划 - 力扣 零钱兑换与完全平方数 深度解析
java·算法·leetcode·动态规划·状态转移
xiaoye-duck2 小时前
《算法题讲解指南:优选算法-滑动窗口》--09长度最小的子数串,10无重复字符的最长字串
c++·算法
Frostnova丶2 小时前
LeetCode 762 二进制表示中质数个计算置位
算法·leetcode