2021年3月7日之前学习记录

博主分享了每日的学习计划,包括做题和总结,主要涉及PAT、蓝桥杯、牛客、力扣等平台的编程题目。在CTF学习中,重点复习了文件分析、分离与合并,以及斐波那契数列和字符串相加的算法。同时,博主遇到一道字符串相乘的难题,尚未解决。此外,还介绍了图片隐写的相关知识。

学习记录

每日任务有两项:做题和总结当天所学知识。做题由简单到困难,刷题顺序是PAT->蓝桥杯->牛客->力扣->PAT···
写博客进行自我监督
day 4,5,6 ×

反思篇

首先本人反思了一下为什么会断更3天。第四天的时候确实偷懒了,第五天准备蓝桥杯校选,考之前也做了PAT的题目,因为题目相对较简单就没有写。虽然说学习CTF有点收获,但总体的来说还是偷懒了。那偷懒了两天应该意识到才对?其实我意识到了,但是因为昨天做的蓝桥杯属实把我整晕了一个字符串相乘就把我整晕了(虽然说那题可以采用最大公约数来求,待会细说)。


day 4
day 4是菜鸡的记录,因为开了kali虚拟机,靶机,浏览器(本人内存16G)。这时候我就想:靶机也算是一种有漏洞的程序吧?这时候我就想到了我电脑上也有win10系统啊,放在里面不就好了?然后我点开了分配8G内存的win10。。这个时候电脑开始爆卡,关也关不掉。重启电脑还发现内存少了一根?自此那天一直忙到了凌晨1:30左右终于是搞得差不多了。但现在用起来还是有vmware还是有后遗症。
day 5
参加了校选赛,参赛前也抽空学了CTF。(校选有一题很简单但是居然忘记了怎么写,为day 6蓝桥练习做了铺垫)
day 5 CTF学习总结
CTF杂项:
  1. 文件的分离
  2. 文件的合并

对于文件分离

  1. 若不确定考察的是文件分离,首先要进行文件的分析,出题人可以将不同类型的文件合在一起。分析(或)分离工具有:binwalk foremost dd 010editer
  2. 若确定考察的是文件分离,则直接使用上述分析(或)分离工具直接解题即可。

分析(或)分离工具的使用:

命令分析命令分离命令
binwalkbinwalk 文件名binwalk -e 文件名
foremostforemost 文件名 -o 目录名
dddd if=源文件 of=生成文件 bs=块大小 count=所需块数 [skip=跳过块数]
010editer打开后认为分析选中文件对应的16进制编码手动另存为即可

dd命令的例子:
已知文件1.txt中的内容为1234567890abcdefg
命令:dd if=1.txt of=2.txt bs=5 count=3 skip=1
得到的2.txt内容为:67890abcdefg

对于文件合并
出题人可能会将一个文件分成多个文件,并且打乱顺序。如果明确了考的是文件合并,那么就可以使用文件合并的工具来解题。(合成顺序应该只能自己寻找了)

文件合成命令:

操作系统命令
windowscopy /B xxx+xxx··· 生成文件名.格式
kalicat xxx xxx··· > 文件名

合成文件后需要确定是否合成正确,怎么检测合成是否正确?检测合成文件的md5值即可。

md5检测命令:

操作系统命令
windowscertutil -hashfile xxx.xxx md5
kalimd5sum xxx.xxx

day 6
悲惨的编程经历
有一道校选的题是这样的:存在一个这样的规律,第一第二个数分别为0,1。第三 个数开始大小等于前两个数字相加求120个是多大。
分析:
典型的斐波那契数列,但是这里的数字肯定会很大,所以我们应该采取的是字符串相加而不是数字相加。

参考程序如下:

/**
 * 题目:
 * 存在一种规律,第一天为0,第二天为1,从第三天开始数字为前两天相加。求地120天的数字
 */
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

void sum(char* s1,char* s2,char* s3){   // 使用指针的形式就能直接改变实参
    int index1,index2,index3 = 0;
    index1 = strlen(s1) - 1;
    index2 = strlen(s2) - 1;
    int jin = 0;
    while(index1 >= 0 || index2 >= 0){
        if(index1 >= 0 && index2 >= 0){
            s3[index3++] = (s1[index1]-'0' + s2[index2]-'0' + jin) % 10 + '0';
            jin = (s1[index1]-'0' + s2[index2]-'0' + jin) / 10;
        }else{
            s3[index3++] = (s2[index2]-'0' + jin) % 10 + '0';
            jin = (s2[index2]-'0' + jin) / 10;
        }
        --index1;
        --index2;
    }
    if(jin > 0){
        s3[index3++] = '1';
    }
    s3[index3] = '\0';  // 强制结束字符串防止出现错乱的字符
}

int main()
{
    char s1[1000] = "0";
    char s2[1000] = "1";
    char s3[1000];
    for(int i = 3;i <= 120;i++){
        sum(s1,s2,s3);
        // 逆序
        for(int i = 0;i < strlen(s3) / 2;i++){
            char t = s3[i];
            s3[i] = s3[strlen(s3)-1 - i];
            s3[strlen(s3)-1 - i] = t;
        }
        strcpy(s1,s2);
        strcpy(s2,s3);
    }
    printf("%s",s3);
    system("pause");
    return 0;
}

可以的到答案为:3311648143516982017180081


题目:ADV-384 求1加到x的和(number)
按照题目来就行,使用简单的求和公式即可(1+n)*n/2
参考程序如下:

#include<stdio.h>
#include<stdlib.h>

int main()
{
    int n;
    long long sum = 0;
    scanf("%d",&n);
    printf("%lld",(1+n)*n/2);
    system("pause");
    return 0;
}

我宣布day 6的梦魇正式登场:
题目:
求C(n,m)%p,且1<=n, m<=60000, 1<p<=1000000007。
此题理解:
因为n!(m!)(n−m)!\displaystyle {\frac{n!}{(m!)(n-m)!} }(m!)(nm)!n!中我们可以校区他们中的任意一个,如果n与n-m之间,谁大消去谁,相等消去m。剩下的用最大公约数来求解应该就可以了。但是但是,我就是要用字符串相乘来求解(直至现在都没有完成。。。)

未完成的代码:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void jia(char *sum1,char *sum2){
    int index1,index2;
    index1 = 0;
    index2 = -1;
    int jin = 0;
    while(index1 <= strlen(sum1)-1 || index2 <= strlen(sum2)-1){
        if(index1 <= strlen(sum1)-1 && index2 <= strlen(sum2)-1){
            char t = sum1[index1];
            sum1[index1] = (t -'0' + sum2[index2]-'0' + jin) % 10 + '0';
            jin = (t -'0' + sum2[index2]-'0' + jin) / 10;
        }else if(index2 < 0){
            
        }else if(index1 >= strlen(sum1)){
            sum1[index1] = (sum2[index2]-'0' + jin) % 10 +'0';
            jin = (sum2[index2]-'0' + jin) / 10;
        }
        ++index1;
        ++index2;
    }
    if(jin > 0){
        sum1[index1++] = jin + '0';
    }
    sum1[index1] = '\0';
}

void nixu_a(char *a){
    // 逆序
    for(int i = 0;i < strlen(a)/2;i++){
        char t = a[i];
        a[i] = a[strlen(a)-1 - i];
        a[strlen(a)-1 - i] = t;
    }
}

void nixu_sum1(char *sum1){
    // 逆序
    for(int i = 0;i < strlen(sum1)/2;i++){
        char t = sum1[i];
        sum1[i] = sum1[strlen(sum1)-1 - i];
        sum1[strlen(sum1)-1 - i] = t;
    }
}

void cheng(char *num1,char *num2,int n,int flag){
    int index = 0;
    char sum1[100];
    char sum2[100];
    int sum1_i = 0;
    int sum2_i;
    int num1_i = strlen(num1)-1;
    int jin;
    if(flag == 1){
        char a[100];
        while(n != 0){
            a[index++] = n % 10 + '0';
            n /= 10;
        }
        a[index] = '\0';
        nixu_a(a);
        // num1 & a相乘
        for(int j = index-1;j >= 0;j--){
            sum2_i = 0;
            jin = 0;
            for(int i = num1_i;i >= 0;i--){
                sum2[sum2_i++] = ((num1[i]-'0') * (a[j]-'0') + jin)%10 + '0';
                jin = ((num1[i]-'0') * (a[j]-'0') + jin) / 10;
            }
            if(jin > 0){
                sum2[sum2_i++] = jin + '0';
            }
            sum2[sum2_i] = '\0';
            if(j == index-1){
                strcpy(sum1,sum2);
            }else{
                jia(sum1,sum2);
            }
        }
        nixu_sum1(sum1);
        strcpy(num1,sum1);
    }
}

// void chu()

int main()
{
    int n,m;
    int n_;
    char num[100];
    char num1[100];
    char num2[100];
    scanf("%d %d %s",&n,&m,num);
    n_ = n;
    for(int i = 1;i <= n_-m;i++){
        if(i != 1){
            cheng(num1,num2,n,1);
        }else{
            int index = 0;
            int check = n;
            while(check != 0){
                num1[index++] = check % 10 + '0';
                check /= 10;
            }
            num1[index] = '\0';
            for(int j = 0;j < index/2;j++){
                char t = num1[j];
                num1[j] = num1[index-1 - j];
                num1[index-1 - j] = t;
            }
        }
        --n;
    }
    printf("%s",num1);
    system("pause");
    return 0;
}

day 6 CTF学习总结
CTF杂项:图片隐写
对于图片隐写
  1. 可能藏在图片中的某一帧中,或者某一图层中;
  2. 可能在文件的属性中;
  3. 可能是两个差不多的图片进行XOR,ADD,SUB的操作(SUB是有先后顺序的A-B与B-A并不相同);
  4. LSB修改RGB的最低比特位达到隐藏图片的目的;
  5. 可能会破坏文件头,或者修改CRC值,若CRC没错则可能是图片宽度或者高度被篡改。

情况1:
藏在某一帧或者某一图层中,直接使用fireworks,ps打开即可。
情况2:
查看文件属性即可。
情况3:
使用Stegsolve这个java程序对两个文件进行相对应的操作即可。
情况4:
kali中使用zsteg xxx.png即可分析(只能用于PNG & BMP格式的文件);
工具2:wbstego4(适用于BMP & PDF);
使用py脚本:

import PIL.Image
def foo():
	im = PIL.Image.open('文件名.文件格式')
	im2 = im.copy()
	pix = im2.load()
	width,height = im2.size
	for x in xrange(0,width):
		for y in xrange(0,height):
			if pix[x,y]&0x1 == 0:
				pix[x,y] = 0
			else:
				pix[x,y] = 255
	im2.show()
	pass
if __name__ == '__main__':
	foo()
	print 'ok'
	pass

情况5:
1.恢复文件头
2.使用TweakPNG进行PNG图片的CRC检验
3.若CRC无错但是依然无法得到对应的flag则使用py脚本检验图片的宽和高是否被修改
py脚本如下:

import binascii
import struct
crcbp = open("xxx.png","rb").read()
for i in range(1024):
	for j in range(1024):
		data = crcbp[12:16] + struct.pack('>i',i) + struct.pack('>i',j) + crcbp[24:29]
		crc32 = binascii.crc32(data) & 0xffffffff
		if crc32 == 0x12345678:
			print i,j
			print "hex",hex(i),hex(j)





于2021年3月7日09点44分完成博客编写,若发现错误望指正。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值