2021-9-23 base64学习

逆向解密

base64

基本概念:

base64根据百度的查询,定义如下:
	Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64个可打印字符来表示二进制数据的方法。
    //64个字符为:ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=

基本原理:

即把一个3字节的数据转换为4字节的数据存储-----以二进制的形式进行操作。
假设现在要对"abc"这串字符串进行base64加密,首先判断该数据是否为 3的倍数的 字节大小(其中一个字符1字节,一个字节可以用8个二进制表示)
    该数据确定为3字节大小的倍数后根据ascii码对应的二进制表示出来

在这里插入图片描述

	将二进制每6位为一组,然后高位补00,形成8位一组
    然后将其二进制对应的base64表中的值去对应相应的base64码
	最后就能得到base64加密的字符串
        ”YWJj"

在这里插入图片描述

若加密的数据不足3的倍数的字节的大小,那么就在其 编码过程 中补\x00,补足其位数,补了几个\x00,最后就加上几个'='
    现要加密字符'1'//其ascii表对应的二进制为0011 0001(49)
    操作如下和正常情况加密相似

base64表如下:
在这里插入图片描述

​ 摘自百度

C语言实现

#include<stdio.h>
#include<string.h>
#define MAX 100000
char base64[]={"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="};//base64表 
char decode(char flag[]);
int main(){
	char text[MAX];
	scanf("%s",&text);
	int i=0;
	int j=0;
	long len=strlen(text);
	char flag[MAX];
	int v4=len%3;
	switch(v4){
		//字符串是3的倍数长度的情况 
		case 0:{
			len=(strlen(text)/3)*4;
			for(i=0;i<len;){
				flag[i]=base64[text[j]>>2];//取第一位元素text[0]的前6位 
				flag[i+1]=base64[ ( ( text[j] & 0x3 ) << 4 ) | ( ( text[j+1] >> 4 ) ) ];//取第一位元素text[0]的后两位和第二元素text[1]的前4位 
				flag[i+2]=base64[((text[j+1]&0xf)<<2)|((text[j+2]&0xc0)>>6)];//取text[1]的后4位和text[2]的前2位 
				flag[i+3]=base64[text[j+2]&0x3f];//取text[2]的后六位 
				i=i+4;
				j=j+3;
			}
			break;
		}
		//长度比3的倍数多一的情况 
		case 1:{
			len=(strlen(text)/3)*4;
			//先对前面3的倍数的长度经行正常规则编码 
			for(i=0;i<len;){
				flag[i]=base64[text[j]>>2];
				flag[i+1]=base64[ ( ( text[j] & 3 ) << 4 ) | ( ( text[j+1] >> 4 ) ) ]; 
				flag[i+2]=base64[((text[j+1]&0xf)<<2)|((text[j+2]&0xc0)>>6)];
				flag[i+3]=base64[text[j+2]&0x3f];
				i=i+4;
				j=j+3;
			}
			//再对多出来的字符以在二进制末尾补充/x00的形式进行编码,末尾填写多少个/x00就在编码末尾添加几个‘=’ 
			flag[i]=base64[text[j]>>2];
			flag[i+1]=base64[ ( ( text[j] & 3 ) << 4 ) | ( ( text[j+1] >> 4 ) ) ]; 
			flag[i+2]=base64[strlen(base64)-1];// '='
			flag[i+3]=base64[strlen(base64)-1];// '='
			break;
		}
		//长度比3的倍数多2的情况 
		//编码规则和多1的一样 
		case 2:{
			len=(strlen(text)/3)*4;
			for(i=0;i<len;){
				flag[i]=base64[text[j]>>2];
				flag[i+1]=base64[ ( ( text[j] & 3 ) << 4 ) | ( ( text[j+1] >> 4 ) ) ]; 
				flag[i+2]=base64[((text[j+1]&0xf)<<2)|((text[j+2]&0xc0)>>6)];
				flag[i+3]=base64[text[j+2]&0x3f];
				i=i+4;
				j=j+3;
			}
			flag[i]=base64[text[j]>>2];
			flag[i+1]=base64[ ( ( text[j] & 3 ) << 4 ) | ( ( text[j+1] >> 4 ) ) ]; 
			flag[i+2]=base64[((text[j+1]&0xf)<<2)|((text[j+2]&0xc0)>>6)];
			flag[i+3]=base64[strlen(base64)-1];// '='
			break;
		}
	}
	printf("%s\n",flag);
	decode(flag);//base64的解码 
	return 0;
}
char decode(char flag[]){
	char base64[MAX];
	base64['A']=0;
	base64['B']=1;
	base64['C']=2;
	base64['D']=3;
	base64['E']=4;
	base64['F']=5;
	base64['G']=6;
	base64['H']=7;
	base64['I']=8;
	base64['J']=9;
	base64['K']=10;
	base64['L']=11;
	base64['M']=12;
	base64['N']=13;
	base64['O']=14;
	base64['P']=15;
	base64['Q']=16;
	base64['R']=17;
	base64['S']=18;
	base64['T']=19;
	base64['U']=20;
	base64['V']=21;
	base64['W']=22;
	base64['X']=23;
	base64['Y']=24;
	base64['Z']=25;
	base64['a']=26;
	base64['b']=27;
	base64['c']=28;
	base64['d']=29;
	base64['e']=30;
	base64['f']=31;
	base64['g']=32;
	base64['h']=33;
	base64['i']=34;
	base64['j']=35;
	base64['k']=36;
	base64['l']=37;
	base64['m']=38;
	base64['n']=39;
	base64['o']=40;
	base64['p']=41;
	base64['q']=42;
	base64['r']=43;
	base64['s']=44;
	base64['t']=45;
	base64['u']=46;
	base64['v']=47;
	base64['w']=48;
	base64['x']=49;
	base64['y']=50;
	base64['z']=51;
	base64['0']=52;
	base64['1']=53;
	base64['2']=54;
	base64['3']=55;
	base64['4']=56;
	base64['5']=57;
	base64['6']=58;
	base64['7']=59;
	base64['8']=60;
	base64['9']=61;
	base64['+']=62;
	base64['/']=63;
	//建立base64表 ,后续根据base64表对应的十进制进行移位操作,到达解码的目的 
	int i=0;
	int j=0;
	int len=strlen(flag);
	//判断原始明文长度 
	if(flag[len-1]=='='&&flag[len-2]!='=')
		len=len/4*3-1;
	else if(flag[len-2]=='=')
		len=len/4*3-2;
	else
		len=len/4*3;
 
	char text[len];
	for(i=0;i<len;){
		text[i]=(base64[flag[j]]<<2)|((base64[flag[j+1]]<<2)&0x60)>>6;//取flag[0]的后六位和flag[1]的前2位 
		text[i+1]=(base64[flag[j+1]]<<4)|(base64[flag[j+2]]<<2)>>4;//取flag[1]的后4位和flag[2]的中间4位
		text[i+2]=(base64[flag[j+2]]<<6)|base64[flag[j+3]]&0x3f; //取flag[2]的后2位和flag{3]的后6位 
		i=i+3;
		j=j+4;
	}
	printf("%s",text); 
	return *text;
}

关于base64的题

BUUCTF-reverse-3

IDA32打开进行分析

没找到main函数,然后打开string window界面,找到”right flag!“字符串跟进去,对该部分函数进行分析

在这里插入图片描述

int sub_4156E0()
{
  int v0; // eax@6
  int v1; // eax@6
  size_t v2; // eax@9
  char v4; // [sp+0h] [bp-188h]@6
  char v5; // [sp+Ch] [bp-17Ch]@1
  size_t v6; // [sp+10h] [bp-178h]@3
  size_t j; // [sp+DCh] [bp-ACh]@6
  size_t i; // [sp+E8h] [bp-A0h]@1
  char Dest[108]; // [sp+F4h] [bp-94h]@5
  char Str; // [sp+160h] [bp-28h]@6
  char v11; // [sp+17Ch] [bp-Ch]@6
  unsigned int v12; // [sp+184h] [bp-4h]@1
  int savedregs; // [sp+188h] [bp+0h]@1

  memset(&v5, 0xCCu, 0x17Cu);
  v12 = (unsigned int)&savedregs ^ __security_cookie;
  for ( i = 0; (signed int)i < 100; ++i )
  {
    v6 = i;
    if ( i >= 0x64 )
      sub_411154();
    Dest[v6] = 0;
  }
  sub_41132F("please enter the flag:", v4);
  sub_411375("%20s", &Str);                     // Str字符串就是flag
  v0 = j_strlen(&Str);                          // V0表示flag的长度
  v1 = sub_4110BE((int)&Str, v0, (int)&v11);    // 调用函数sub_4110BE进行加密str操作,同时加密后的代码返回给V1
  strncpy(Dest, (const char *)v1, 0x28u);       // 将加密后的flag也就是v1复制到Dest里面
  sub_411127();
  i = j_strlen(Dest);
  for ( j = 0; (signed int)j < (signed int)i; ++j )// 对加密后的flag也就是Dest中的每个元素加j操作
    Dest[j] += j;                               // Dest[j]=Dest[j]+j;
  v2 = j_strlen(Dest);
  strncmp(Dest, Str2, v2);                      // 比较Dest和Str2,也就是说Str2是最终的加密flag
  if ( sub_411127() )                           // Str2为e3nifIH9b_C@n@dH
    sub_41132F("wrong flag!\n", v4);
  else
    sub_41132F("rigth flag!\n", v4);
  sub_41126C(&savedregs, &dword_415890);
  sub_411280();
  return sub_411127();
}

顺着分析下来,其主要的加密部分为

v1 = sub_4110BE((int)&Str, v0, (int)&v11);    // 调用函数sub_4110BE进行加密str操作,同时加密后的代码返回给V1
//和
for ( j = 0; (signed int)j < (signed int)i; ++j )// 对加密后的flag也就是Dest中的每个元素加j操作
    Dest[j] += j;                               // Dest[j]=Dest[j]+j;

主要跟进sub_4110BE函数

在这里插入图片描述

这部分代码就是对传进来的字符串进行base64加密,v4判断本次循环的byte_41A144[0][1][2]是否有3字节的大小
    然后根据v4的情况进行加密,满足3字节的话,就进第三个判断,正常加密,
    不满足3字节的就进行补\x00操作,然后加几个\x00就在末尾添几个'='

从该函数跳出后,加密后的字符串被传给了v1,然后又被copy到Dest上,之后又对Dest修改

for ( j = 0; (signed int)j < (signed int)i; ++j )// 对加密后的flag也就是Dest中的每个元素加j操作
    Dest[j] += j;                               // Dest[j]=Dest[j]+j;

最后Dest只有等于Str2才输出”right flag“

所以就是解题步骤如下:

#include<stdio.h>
#include<windows.h>
#include<string.h>
int main(){
    int v4;
    char a[20]={"e3nifIH9b_C@n@dH"};
    int i;
    for(i=0;i<strlen(a);i++){
        a[i]=a[i]-i;
    }
    //memset( &v4,0xCCu,0x100u);
    printf("%s\n",a);
    system("pause");
    return 0;

得原来的base加密后的字符为:e2lfbDB2ZV95b3V9,通过网上的base64解密得flag:

flag{i_l0ve_you}

0x100u);
printf("%s\n",a);
system(“pause”);
return 0;


得原来的base加密后的字符为:==e2lfbDB2ZV95b3V9==,通过网上的base64解密得flag:

flag{i_l0ve_you}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值