FCTF&BUU题解

FTCF

[简单]Xor

本题考查异或

规则0^0=0  1^0=1 0^1=1 1^1=0

将文件打开得到如下

修改代码得到flag

 ​​​​​​​

FCTF{You_Are_Great_Xor_is_Very_Easy} 

 FlowerDance

本题考查花指令

拖入exe发现是32位

拖入ida,很明显的花指令标志

花指令简单操作

1. Edit>Patch program>change byte

2. 将e8修改为90(nop) 也可以快捷键ctrl+n直接nop

3. nop完可能被认为是数据 需要按c重新识别为代码

4.找到main函数按p(重新识别成代码 创建函数),按空格到主界面,再按f5出现伪c代码

 

 分析函数

 

写出解密代码

#include<stdio.h>
#include<string.h>
int main()
{
	char v7[]={"JunkCode"};
	char Buf1[]=
	{ 
	'F','k','b','X','X','L',12,'^','$','i','P',
	127,100,33,56,112,82,47,62,29,100,
	35,125,116,74,96,8,74 };
	int j=26;
	for (int i = 0; i < 27; ++i )
	{
		Buf1[i+1]^= v7[j % 8] ^ Buf1[i];
		j--;
	}  
   puts(Buf1);
   return 0;
 } 

 FCTF{S0-be@ut1fUl-f10weRs}

 

BUU 

内涵的软件

本题考查中文字符串的显示

在ida中可能无法正常显示 需要手动设置编码步骤如下:

1.options>general>strings
2.双击UTF-8,鼠标右键insert
3.在弹出的框中输入gbk,保存确认
4.选中需要修复的字符串,按ALT+A
5.选择C-style,中文字符成功显示

先将文件拖入exe进行查看,后在ida中打开文件xor,点击main函数进入

进入main函数,F5得到伪代码,观察代码

转换成中文字符,R将数字转换成字母,最后得出flag即为{49d3c93df25caad81232130f3d2ebfad}

 

flag{49d3c93df25caad81232130f3d2ebfad} 

新年快乐

本题主要考察脱壳和对upx的使用

先将文件拖入exe进行查看,然后对其进行脱壳处理,并且显示文件为32位

将文件拖入upx文件夹之后打开,脱壳处理为upx -d+文件名,下图表示脱壳成功,成功后拖入ida

strcpy()函数:是将一个字符串复制到另一块空间地址中 的函数,‘\0’是停止拷贝的终止条件,同时也会将 '\0' 也复制到目标空间

分析下面代码,将str2复制到str1,即str2为flag

flag{HappyNewYear!} 

xor

本题考查异或

规则0^0=0  1^0=1 0^1=1 1^1=0

在ida中打开文件c,由分析可知,b[i]与b[i-1]做异或后再与global做比较

跟进global得到字符,shift+E提取数据得到十进制形式


 

写出如下脚本

flag{QianQiuWanDai_YiTongJiangHu}

 赣CTF题解

find_flag

本题考查tea加密和fack flag的情况(找main函数之前执行的)

加密过程中:

存在一个delta值,这个值会不停的增加到sum之中,形成一种循环的效果
传入的v0,v1会和传入的key0,key1运算。v1优先参与,并且会有一个位移->与密钥相加->异或的过程。
v0 = 原先的v1值套用公式,v1 = 变化后的v0 套用公式
之前用于计算delta的sum状态值也会参与
由于是一个类似delta状态变化+异或加密的过程,所以整个流程反过来写即可得到解密
原文链接:https://blog.csdn.net/m0_73393932/article/details/130094306

#include <stdio.h>
#include <stdint.h>
 
//加密函数
void encrypt (uint32_t* v, uint32_t* k) {
    uint32_t v0=v[0], v1=v[1], sum=0, i;     //v0,v1分别为字符串的低字节高字节     
    uint32_t delta=0x9e3779b9;                    
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; 
    for (i=0; i < 32; i++) {               //加密32轮        
        sum += delta;
        v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
    }                                             
    v[0]=v0; v[1]=v1;//加密后再重新赋值
}
//解密函数
void decrypt (uint32_t* v, uint32_t* k) {
    uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i;  
    uint32_t delta=0x9e3779b9;                     
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];  
    for (i=0; i<32; i++) {                        //解密时将加密算法的顺序倒过来,还有+=变为-=
        v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
        v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        sum -= delta;
    }                                              
    v[0]=v0; v[1]=v1;//解密后再重新赋值
}
 
int main()
{
    uint32_t v[2]={1,2},k[4]={2,2,3,4};
    // v为要加密的数据是两个32位无符号整数
    // k为加密解密密钥,为4个32位无符号整数,即密钥长度为128位
    printf("加密前原始数据:%u %u\n",v[0],v[1]);
    encrypt(v, k);
    printf("加密后的数据:%u %u\n",v[0],v[1]);
    decrypt(v, k);
    printf("解密后的数据:%u %u\n",v[0],v[1]);
    return 0;
}

​ 本题考查tea加密拖入exe发现是64位


​编辑观察,每8个字节一组


​编辑 跟进sub_401641,这是一个tea加密


 将其改为标准tea加密(N修改变量名称)


​编辑继续观察 ,提取data,shift+e不够的情况下,按一下*号再shift+e

写出脚本,得到flag{You_found_the_flag!But_is_a_FAKE~}这是一个假的flag

#include <stdio.h>
#include <stdint.h>
 
//加密函数
void encrypt (uint32_t* v, uint32_t* k) {
    uint32_t v0=v[0], v1=v[1], sum=0, i;     //v0,v1分别为字符串的低字节高字节     
    uint32_t delta=0x9e3779b9;                    
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; 
    for (i=0; i < 32; i++) {               //加密32轮        
        sum += delta;
        v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
    }                                             
    v[0]=v0; 
	v[1]=v1;//加密后再重新赋值
}
//解密函数
void decrypt (uint32_t* v, uint32_t* k) {
    uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i;  
    uint32_t delta=0x9e3779b9;                     
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];  
    for (i=0; i<32; i++) {                        //解密时将加密算法的顺序倒过来,还有+=变为-=
        v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
        v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        sum -= delta;
    }                                              
    v[0]=v0; 
	v[1]=v1;//解密后再重新赋值
}
 
int main()
{

    unsigned int key[4] = { 0x12,0x34,0x56,0x78 };
    unsigned char data[] =
{
  246, 209, 106, 255,  85, 178, 123, 179, 152,  39, 
  152, 219,   3, 185,  61,   8, 189, 104, 155, 211, 
   24,   6,  24, 231, 197,  67, 206, 130, 254, 130, 
  209, 161, 116, 168,  38,  71, 140,  60, 224, 106
};   
for (int i = 0; i < 5; i++)
    decrypt((unsigned int*)data + i * 2, key);
    puts((char*)data);
    return 0;
}

寻找真的flag

找exports,执行顺序在main函数之前,先执行TlsCallback

对input或者data交叉应用 

对input按X( 查看交叉引用),发现main函数前面还有一个函数使用了input

跟进,然后进行动态调试 

进行动态调试,v4从下标3开始 ,前面三个字节归属right,right占了8个字符,七个打印字符,一个0结束符

 

跟进函数

发现是tea的魔改,后续还要修复ke有,只传进data,16在二进制是10000,乘16就相当于左移4位

然后跟进data,按*号设置成40位数组,shift+e提取

 写出代码得到真的flag

#include <stdio.h>
#include <stdint.h>
 
//加密函数
void encrypt (uint32_t* v, uint32_t* k) {
    uint32_t v0=v[0], v1=v[1], sum=0, i;     //v0,v1分别为字符串的低字节高字节     
    uint32_t delta=0x9e3779b9;                    
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3]; 
    for (i=0; i < 32; i++) {               //加密32轮        
        sum += delta;
        v0 += ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        v1 += ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
    }                                             
    v[0]=v0; 
	v[1]=v1;//加密后再重新赋值
}
//解密函数
void decrypt (uint32_t* v, uint32_t* k) {
    uint32_t v0=v[0], v1=v[1], sum=0xC6EF3720, i;  
    uint32_t delta=0x9e3779b9;                     
    uint32_t k0=k[0], k1=k[1], k2=k[2], k3=k[3];  
    for (i=0; i<32; i++) {                        //解密时将加密算法的顺序倒过来,还有+=变为-=
        v1 -= ((v0<<4) + k2) ^ (v0 + sum) ^ ((v0>>5) + k3);
        v0 -= ((v1<<4) + k0) ^ (v1 + sum) ^ ((v1>>5) + k1);
        sum -= delta;
    }                                              
    v[0]=v0; 
	v[1]=v1;//解密后再重新赋值
}
 
int main()
{

    unsigned int key[4] = { 137,118,84,50 };
    unsigned char data[] =
{
  107, 121,  31, 159, 120, 115, 175, 228, 213, 223, 
  252, 114, 224, 255,  87,  74,   7, 186, 114,  22, 
  230, 123,   5, 170, 142,  31,  23, 158,  79,  62, 
   21, 221,  89, 158,   7,  65, 221, 120, 117, 128
};  
for (int i = 0; i < 5; i++)
    decrypt((unsigned int*)data + i * 2, key);
    puts((char*)data);
    return 0;
}

flag{W0w!You_F1nd_mE!_coNgr@tulAt1ons!}

BrownFox

加密算法

The quick brown fox jumps over the lazy dog!
       ihxo{smzdodcikmodcismzd}
解:
背景和案例:
一种 Playfair密码变种加密方法如下:首先选择一个密钥单词(称为 pair)(字母不重复,且都为小写字母),
然后与字母表中其他字母一起填入至一个 5x5的方阵中,填入方法如下:


1.选取一个英文字作密钥。除去重复出现的字母。将密匙的字母逐个逐个加入5×5的矩阵内,(本题没有)剩下的空间将未加入的英文字母依a-z的顺序加入。
  (将I和J视作同一字。JOY -> IOY)将要加密的讯息分成两个一组。
2.在每组中,找出两个字母在矩阵中的地方。
3.若两个字母同列,取这两个字母上下方的字母(若字母在最上方则取最下方的字母)。
4.若两个字母同行,取这两个字母左右方的字母(若字母在最左方则取最右方的字母)。
5.若两个字母不同行也不同列,在矩阵中找出另外两个字母,使这四个字母成为一个长方形的四个角(am->ob)。
6.新找到的两个字母就是原本的两个字母加密的结果。


如果密钥为 youandme,则该方阵如下:
y o u a n
d m e b c
f g h i j
k l p q r
s t v w x
在加密一对字母时,如 am,在方阵中找到以这两个字母为顶点的矩形(红色字体):
y o u a n
d m e b c
f g h i j
k l p q r
s t v w x
这对字母的加密字母为该矩形的另一对顶点,如本例中为 ob。
原文链接:https://blog.csdn.net/dongyanwen6036/article/details/76719570

 拖入exe发现是64,在拖入ida

按F5进入后,分析main函数首先给data赋值,接收输入后再用to_fox对输入进行加密,加密结果存储到v9数组,再和data数组比较

 进入to_fox,按N修改函数名

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值