题目下载链接:EasyBase
rot13加密
ROT13(回转13位,rotate by 13 places,有时中间加了个连字符称作ROT-13)是一种简易的替换式密码。它是一种在英文网络论坛用作隐藏八卦(spoiler)、妙句、谜题解答以及某些脏话的工具,目的是逃过版主或管理员的匆匆一瞥。ROT13被描述成“杂志字谜上下颠倒解答的Usenet点对点体”。ROT13 也是过去在古罗马开发的凯撒加密的一种变体。
两个连续的ROT13应用函式会回复原始文字(在数学上,这有时称之为对合(involution);在密码学上,这叫做对等加密(reciprocalcipher))。
转换可以利用查找表完成,如下例所示

base64
base64.h头文件
#ifndef _BASE64_H
#define _BASE64_H
#include <stdlib.h>
#include <string.h>
unsigned char *base64_encode(unsigned char *str);
unsigned char *bae64_decode(unsigned char *code);
#endif
base64加密解密
#include<iostream>
#include<cstring>
#include<bitset>
#include<vector>
#include<stdlib.h>
#include<time.h>
#include<sstream>
#include<cstring>
/*base64.c*/
#include "base64.h"
using namespace std;
//base64.c
#include"base64.h"
char base64char[] = {
'A','B','C','D','E','F','G','H','I','J',
'K','L','M','N','O','P','Q','R','S','T',
'U','V','W','X','Y','Z','a','b','c','d',
'e','f','g','h','i','j','k','l','m','n',
'o','p','q','r','s','t','u','v','w','x',
'y','z','0','1','2','3','4','5','6','7',
'8','9','+', '/', '\0'
};
/*
char base64char[] = {
'K','L','M','N','O','P','Q','R','S','T',
'A','B','C','D','E','F','G','H','I','J',
'e','f','g','h','i','j','k','l','m','n',
'U','V','W','X','Y','Z','a','b','c','d',
'o','p','q','r','s','t','u','v','w','x',
'y','z','0','1','2','3','4','5','6','7',
'8','9','+', '/', '\0'
};
*/
char c;
void Menu()
{
printf("***************\n");
printf("*1、base64加密\n");
printf("*2、base64解密\n");
printf("*3、退出程序\n");
printf("***************\n");
}
char* base64_encode(char* binData, char* base64, int binLength)
{
int i = 0;
int j = 0;
int current = 0;
for (i = 0; i < binLength; i += 3) {
//获取第一个6位
current = (*(binData + i) >> 2) & 0x3F;
*(base64 + j++) = base64char[current];
//获取第二个6位的前两位
current = (*(binData + i) << 4) & 0x30;
//如果只有一个字符,那么需要做特殊处理
if (binLength <= (i + 1)) {
*(base64 + j++) = base64char[current];
*(base64 + j++) = '=';
*(base64 + j++) = '=';
break;
}
//获取第二个6位的后四位
current |= (*(binData + i + 1) >> 4) & 0xf;
*(base64 + j++) = base64char[current];
//获取第三个6位的前四位
current = (*(binData + i + 1) << 2) & 0x3c;
if (binLength <= (i + 2)) {
*(base64 + j++) = base64char[current];
*(base64 + j++) = '=';
break;
}
//获取第三个6位的后两位
current |= (*(binData + i + 2) >> 6) & 0x03;
*(base64 + j++) = base64char[current];
//获取第四个6位
current = *(binData + i + 2) & 0x3F;
*(base64 + j++) = base64char[current];
}
*(base64 + j) = '\0';
return base64;
}
char* base64_decode(char const* base64Str, char* debase64Str, int encodeStrLen)
{
int i = 0;
int j = 0;
int k = 0;
char temp[4] = "";
for (i = 0; i < encodeStrLen; i += 4) {
for (j = 0; j < 64; j++) {
if (*(base64Str + i) == base64char[j]) {
temp[0] = j;
}
}
for (j = 0; j < 64; j++) {
if (*(base64Str + i + 1) == base64char[j]) {
temp[1] = j;
}
}
for (j = 0; j < 64; j++) {
if (*(base64Str + i + 2) == base64char[j]) {
temp[2] = j;
}
}
for (j = 0; j < 64; j++) {
if (*(base64Str + i + 3) == base64char[j]) {
temp[3] = j;
}
}
*(debase64Str + k++) = ((temp[0] << 2) & 0xFC) | ((temp[1] >> 4) & 0x03);
if (*(base64Str + i + 2) == '=')
break;
*(debase64Str + k++) = ((temp[1] << 4) & 0xF0) | ((temp[2] >> 2) & 0x0F);
if (*(base64Str + i + 3) == '=')
break;
*(debase64Str + k++) = ((temp[2] << 6) & 0xF0) | (temp[3] & 0x3F);
}
return debase64Str;
}
int main()
{
char ad[]="123456789";
char add[256];
base64_encode(ad,add,strlen(ad));
cout<<add<<endl;
/*
for(int i = 0 ; i < strlen(base64char);i++)
{
printf("%c",base64char[i]);
}
*/
}
strrev函数
概念:
strrev()函数将字符串逆置,其原型为:char strrev(char str);
参数:
str为要逆置的字符串。strrev()将str所指的字符串逆置。
返回值:
返回指向逆置后的字符串的指针。也就是逆序后的结果要用字符串指针类型接收。
注意:
strrev()不会生成新字符串,而是修改原有字符串。因此它只能逆置字符数组,而不能逆置字符串指针指向的字符串,因为字符串指针指向的是字符串常量,常量不能被修改。
实现
void strrev(char *s)
{
if(NULL == s)
return;
char *pBegin = s;
char *pEnd = s + strlen(s) - 1;
char pTemp;
while(pBegin < pEnd)
{
pTemp = *pBegin;
*pBegin = *pEnd;
*pEnd = pTemp;
++ pBegin, -- pEnd;
}
}
题解
前期分析

说实话一进来看到一长串的代码,我当时就慌了,还有这个降龙十八掌是什么鬼,就是非常的离谱,然后我们往下翻可以返现一行倒置的base64;

看到倒置的base64之后先尝试把他倒过来解密
倒置算法
char a[]="=DzMuO8MmgaomuGA9Rmpj5lAkAwZgxQplNGYhOwAi6lAmywZlqGZ7LQB7pGs";
for(int i = 0; i < strlen(a); i ++ )
{
cout<<a[i];
st.push(a[i]);
}
cout<<endl;
int cd =0;
while(!st.empty())
{
cout<<st.top();
a[cd++]=st.top();
st.pop();
}
倒置之后拿到
sGp7BQL7ZGqlZwymAl6iAwOhYGNlpQxgZwAkAl5jpmR9AGumoagmM8OuMzD=
拿去base64解密发现根本无法解密此刻我们就应该想到是不是有什么地方出了问题,由于base64无法解密,肯定是base的字符串被处理过。
解题过程
为了确定程序究竟是如何加密的,动态调试是必不可少的步骤,方便我们动态分析程序,首先我们在程序头下断点然后随便输入一串数据例如abcdefg,然后再跟踪这个字符串。
其中我们会在题目中发现三处显著加密:
Rot13

Base64

Rot13

那么可以发现我们可以看见的密文经历了Rot->Base64->Rot的加密过程然后其中还被进行了倒序,那么我们开始构造解密脚本
[注意]
在本题中对字符串加密的同时在代码的154,204行分别出现了

也就是在解密的同时我们需要注意两次字符串反转!
base64decode:
#include<base64.h>
char* base64_decode(char const* base64Str, char* debase64Str, int encodeStrLen)
{
int i = 0;
int j = 0;
int k = 0;
char temp[4] = "";
for (i = 0; i < encodeStrLen; i += 4) {
for (j = 0; j < 64; j++) {
if (*(base64Str + i) == base64char[j]) {
temp[0] = j;
}
}
for (j = 0; j < 64; j++) {
if (*(base64Str + i + 1) == base64char[j]) {
temp[1] = j;
}
}
for (j = 0; j < 64; j++) {
if (*(base64Str + i + 2) == base64char[j]) {
temp[2] = j;
}
}
for (j = 0; j < 64; j++) {
if (*(base64Str + i + 3) == base64char[j]) {
temp[3] = j;
}
}
*(debase64Str + k++) = ((temp[0] << 2) & 0xFC) | ((temp[1] >> 4) & 0x03);
if (*(base64Str + i + 2) == '=')
break;
*(debase64Str + k++) = ((temp[1] << 4) & 0xF0) | ((temp[2] >> 2) & 0x0F);
if (*(base64Str + i + 3) == '=')
break;
*(debase64Str + k++) = ((temp[2] << 6) & 0xF0) | (temp[3] & 0x3F);
}
return debase64Str;
}
Rotdecode:
这里我们进入Rot13加密的函数可以看见这三段语句



我们发现他与传统的rot13不相同,他对数字也进行了加密因此我们需要构造一个新的解密脚本:
void decode(char a[])
{
for(int i = 0 ; i < strlen(a); i ++ )
{
if(a[i]>='0'&&a[i]<='9')
{
a[i]=(a[i]-48+10-5)%10+48;
}
else if(a[i]>='a'&&a[i]<='z')
{
a[i]=(a[i]-97+26-13)%26+97;
}
else if(a[i]>='A'&&a[i]<='Z')
{
a[i]=(a[i]-65+26-13)%26+65;
}
}
}
那么主函数如下:
将base密码反向
char a[]="=DzMuO8MmgaomuGA9Rmpj5lAkAwZgxQplNGYhOwAi6lAmywZlqGZ7LQB7pGs";
for(int i = 0; i < strlen(a); i ++ )
{
st.push(a[i]);
}
cout<<endl;
int cd =0;
while(!st.empty())
{
cout<<st.top();
a[cd++]=st.top();
st.pop();
}
输出为:
sGp7BQL7ZGqlZwymAl6iAwOhYGNlpQxgZwAkAl5jpmR9AGumoagmM8OuMzD=
然后调用rotdecode
decode(a);
fTc2ODY2MTdyMjlzNy1vNjBuLTAycDktMjNxNy0wczE4NThzbntzZ3BhZmQ=
base64解密
}7686617r29s7-o60n-02p9-23q7-0s1858sn{sgpafd
此时发现flag模样已经有了,我们需要但是似乎是反的,我们需要将其反向,再rot13得到
qsnctf{af3036f5-2d87-4c75-a51b-2f47e2611312}
exp
#include<iostream>
#include<stack>
#include<cstring>
#include<string>
using namespace std;
stack<char> st;
#include "base64.h"
using namespace std;
//base64.c
#include"base64.h"
char base64char[] = {
'A','B','C','D','E','F','G','H','I','J',
'K','L','M','N','O','P','Q','R','S','T',
'U','V','W','X','Y','Z','a','b','c','d',
'e','f','g','h','i','j','k','l','m','n',
'o','p','q','r','s','t','u','v','w','x',
'y','z','0','1','2','3','4','5','6','7',
'8','9','+', '/', '\0'
};
char c;
char* base64_decode(char const* base64Str, char* debase64Str, int encodeStrLen)
{
int i = 0;
int j = 0;
int k = 0;
char temp[4] = "";
for (i = 0; i < encodeStrLen; i += 4) {
for (j = 0; j < 64; j++) {
if (*(base64Str + i) == base64char[j]) {
temp[0] = j;
}
}
for (j = 0; j < 64; j++) {
if (*(base64Str + i + 1) == base64char[j]) {
temp[1] = j;
}
}
for (j = 0; j < 64; j++) {
if (*(base64Str + i + 2) == base64char[j]) {
temp[2] = j;
}
}
for (j = 0; j < 64; j++) {
if (*(base64Str + i + 3) == base64char[j]) {
temp[3] = j;
}
}
*(debase64Str + k++) = ((temp[0] << 2) & 0xFC) | ((temp[1] >> 4) & 0x03);
if (*(base64Str + i + 2) == '=')
break;
*(debase64Str + k++) = ((temp[1] << 4) & 0xF0) | ((temp[2] >> 2) & 0x0F);
if (*(base64Str + i + 3) == '=')
break;
*(debase64Str + k++) = ((temp[2] << 6) & 0xF0) | (temp[3] & 0x3F);
}
return debase64Str;
}
void decode(char a[])
{
for(int i = 0 ; i < strlen(a); i ++ )//数字解密
{
if(a[i]>='0'&&a[i]<='9')
{
a[i]=(a[i]-48+10-5)%10+48;
}
else if(a[i]>='a'&&a[i]<='z')
{
a[i]=(a[i]-97+26-13)%26+97;
}
else if(a[i]>='A'&&a[i]<='Z')
{
a[i]=(a[i]-65+26-13)%26+65;
}
}
}
int main()
{
char a[]="=DzMuO8MmgaomuGA9Rmpj5lAkAwZgxQplNGYhOwAi6lAmywZlqGZ7LQB7pGs";
decode(a);
for(int i = 0; i < strlen(a); i ++ )
{
st.push(a[i]);
}
cout<<endl;
int cd =0;
while(!st.empty())
{
cout<<st.top();
a[cd++]=st.top();
st.pop();
}
cout<<endl;
char key[256];
base64_decode(a,key,strlen(a));
for(int i = 0 ; i< strlen(key); i ++ )
{
cout<<key[i];
}
cout<<endl;
for(int i = 0; i < strlen(key); i ++ )
{
st.push(key[i]);
}
cout<<endl;
cd =0;
while(!st.empty())
{
cout<<st.top();
key[cd++]=st.top();
st.pop();
}
decode(key);
cout<<endl;
cout<<key;
}
