Node的一些应用技巧(持续更新)

Node的一些应用技巧(持续更新)

一边学一边记吧..一些能用的到的

puppeteer模拟登陆

对于表单加密,可以简单的用Pupputeer来模拟登陆,遇到前端加密的情况直接爆破密码。同样能够模拟爬虫,比webdriver要省事的多,而且支持document.queryselector,完全模拟浏览器操作

const puppeteer = require('puppeteer');

async function autoLogin(url,username,password){
    const browser = await puppeteer.launch({
        args: [ '--proxy-server=http://127.0.0.1:8080' ],
        headless: false
    });
    const page = await browser.newPage();

    for(var i=0, len=password.length; i<len; i++){
        pwd = password[i];
        await page.goto(url);
        await page.waitForSelector('#login');
        await page.type('#username', username,{ delay: 50 });
        await page.type('#password', pwd,{ delay: 50 });

        await page.click('#btn_click');

        await page.waitFor(200);
        let html = await page.content();
        if(html.indexOf('wrong') < 1){
            break
        }
    }

    // const tokenVal = await page.$eval('#token', input => input.value);
    await browser.close();
    // console.log("[*]got token is:"+tokenVal);

    page.on('error',(err)=>{
        console.log(err)
    });
}

var username = 'admin';
var password = ['password','root','sa','admin','admin123']

autoLogin('http://node.localhost.com/koa-demo/aes.html',username,password);

http发送请求

简单请求

对比python-request的优点在于不造成阻塞

function getack(target){
    return new Promise((resolve,reject)=>{
        let options = {
            url: target,
            headers: {
                'User-Agent': 'request'
            }
        };
        request.get(options, (error,response,body)=>{
            if (!error && response.statusCode == 200) { 
                resolve(body);
            }else{
                reject(error);
            }
        }).on('error', function(err) {
            rehect(err);
        }); 
    })

}

var target = 'http://server.com';

getack(target).then((body)=>{
    console.log(body);
})

携带cookie请求

request默认不带cookie请求,需要启动jar,获取一个jar对象带入options中,同时对其进行setCookie操作

const j = request.jar();
const cookie1 = request.cookie('username=admin');
const cookie2 = request.cookie('userid=123');
j.setCookie(cookie1, target);
j.setCookie(cookie2, target);

let options = {
    url: target,
    jar:j,
    headers: {
        'User-Agent': 'request'
    }
};

request.get(options, (error,response,body)=>{
    if (!error && response.statusCode == 200) { 
        resolve(body);
    }else{
        reject(error);
    }
}).on('error', function(err) {
    reject(err);
}); 

Response内置属性/方法

查看http.ServerResponse类属性和方法:http://nodejs.cn/api/http.html#http_class_http_serverresponse

HTTP-Server

快速搭建

Nodejs提供了内置的http-api,用来作为Server很方便,console出来便于收藏poc

//server.js
var http=require("http");

http.createServer(function(req,res){
    res.writeHead(200,{
        "content-type":"text/plain"
    });
    res.write("hello world");
    console.log(req.url)
    res.end();

}).listen(3000);

console.log("[*]server run on:http://127.0.0.1:3000")

设置Cookie

req.headers.cookie获取请求头的cookie。node中原生http通过setHeader设置cookie,response.setHeader(name, value)方法接收key,value键值对。

http.createServer(function(req,res){
    username = 'admin'
    userid = 1
    res.setHeader("Set-Cookie",[`username=${username}`,`userid=${userid}`]);
    res.writeHead(200,{
        "content-type":"text/plain"
    });
    console.log(req.url);
    res.end('hello world');

}).listen(3000);

当然也可以用JS-Cookie来操作cookie

调试Express框架

调试已启动的Node程序

在 launch.json 中作如下配置,VSCODE添加配置选项可自动添加

{
    // 使用 IntelliSense 了解相关属性。 
    // 悬停以查看现有属性的描述。
    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "attach",
            "name": "Attach by Process ID",
            "processId": "${command:PickProcess}",
            "skipFiles": [
                "<node_internals>/**"
            ]
        }
    ]
}

启动调试之后会让你选择存在的进程号来指定调试程序
image_1dtsvrmsu4ij1hjp1abliqe1nh2m.png-116.6kB

断点位置

Express基于中间键,调试的时候很难找到入口。如果你跟中间键的话,它在加载框架时要加载一堆的中间键(query、inint、session、cookie)这些的很复杂。所以建议直接把断点打在路由中间件Route的dispatch方法上,因为dispacth就是分发路由,转到对应的实现方法
image_1dtses96u3m212l3rk713h615lr9.png-359.5kB

如果你想对中间键进行分析的话,建议把断点打在这里,因为只是进入中间键的第一步,fn是一个回调的函数
image_1dtsfb8ds4ebel43qt60o1rk99.png-366.2kB

相关文章

关于express中间键的加载以及路由的调度,强烈建议看这篇文章express源码分析

应用实例1-某信息工程大学全自动评教

由于贵校老师实在太多了,闲来无事写了个自动评教(默认全好评)。之所以写了一个koa,是因为最初我想挂到机房,同学们拿着cookie在我web端傻瓜式自动评教了。后来我发现贵校的sso的session竟然验证了ip,代码放出来。

const puppeteer = require('puppeteer');
const Koa = require('koa');
const router = require('koa-router');
const bodyParser = require('koa-bodyparser');

const app = new Koa()
const home  = new router()

async function autoFound(url,cookie){
        const browser = await puppeteer.launch({
            headless: false
        });
        const page = await browser.newPage();
        page.on('dialog',(dialog)=>{
            console.log(dialog.message());
            dialog.accept("确定");
        });

        page.on('error',(err)=>{
            console.log(err);
        });

        const cookies = [{
            name: 'semester.id',
            value: '105',
            domain: '210.41.225.2'
            },{
            name: 'JSESSIONID',
            value: cookie,
            domain: '210.41.225.2'
            },{
            name: 'GSESSIONID',
            value: cookie,
            domain: '210.41.225.2'
            }];

        await page.setCookie(...cookies);

        await page.goto(url);
        const result = await page.evaluate(() => {
            var list = [...document.querySelectorAll('td > a')]
            return list.map(el => {
                return {
                url: el.href.trim(),
                name: el.innerText
                }
            })
        })

        var answers = ['老师真好,我很喜欢跟他相处','老师工作认真负责,课后问题及时讲解','在老师的课堂上学到很多知识'];

        for(var i=0, len=result.length;i<len;i++){
            let bufurl = result[i]["url"];
            try{
                await page.goto(bufurl);
                await page.waitForSelector('.option-item');
                await page.click("input[id=option_425_0]");
                await page.click("input[id=option_426_0]");
                await page.click("input[id=option_427_0]");
                await page.click("input[id=option_428_0]");
                await page.click("input[id=option_429_0]");
                await page.click("input[id=option_430_0]");
                await page.click("input[id=option_431_0]");
                await page.click("input[id=option_432_0]");
                await page.click("input[id=option_433_0]");
                await page.click("input[id=option_434_0]");
                await page.click("input[id=option_435_0]");
                await page.click("input[id=option_436_0]");
                await page.click("input[id=option_437_4]");
                await page.click("input[id=option_438_3]");
                await page.click("input[id=option_439_0]");
                await page.click("input[id=option_440_0]");
                await page.type('.answer-textarea', answers[i%3],{ delay: 50 });
                await page.click('#sub');
                await page.waitFor(3000);
                console.log(result[i]['name']+"done!");
            }catch(err){
                try{
                    await page.goto(bufurl);
                    await page.waitForSelector('.option-item');
                    await page.click("input[id=option_382_0]");
                    await page.click("input[id=option_383_0]");
                    await page.click("input[id=option_384_0]");
                    await page.click("input[id=option_385_0]");
                    await page.click("input[id=option_386_0]");
                    await page.click("input[id=option_387_0]");
                    await page.click("input[id=option_388_0]");
                    await page.click("input[id=option_389_0]");
                    await page.click("input[id=option_390_0]");
                    await page.click("input[id=option_391_0]");
                    await page.click("input[id=option_392_0]");
                    await page.click("input[id=option_393_0]");
                    await page.click("input[id=option_502_4]");
                    await page.click("input[id=option_395_3]");
                    await page.click("input[id=option_396_0]");
                    await page.click("input[id=option_397_0]");
                    await page.type('.answer-textarea', answers[i%3],{ delay: 50 });
                    await page.click('#sub');
                    await page.waitFor(3000);
                    console.log(result[i]['name']+"done!");
                }catch(err){
                    await page.goto(bufurl);
                    await page.waitForSelector('.option-item');
                    await page.click("input[id=option_414_0]");
                    await page.click("input[id=option_415_0]");
                    await page.click("input[id=option_416_0]");
                    await page.click("input[id=option_417_0]");
                    await page.click("input[id=option_418_0]");
                    await page.click("input[id=option_419_0]");
                    await page.click("input[id=option_420_0]");
                    await page.click("input[id=option_421_0]");
                    await page.click("input[id=option_422_0]");
                    await page.click("input[id=option_423_0]");
                    await page.click("input[id=option_424_0]");
                    await page.type('.answer-textarea', answers[i%3],{ delay: 50 });
                    await page.click('#sub');
                    await page.waitFor(3000);
                    console.log(result[i]['name']+"done!");
                }
            }
        }
        await browser.close();
}

home.get('/',async(ctx)=>{
    let html = `
    <html>
    <body>
    <p>
        首先登陆jwc.cuit.edu.cn,"量化评教"的学情自己填了(否则不允许评教)
    </p>
    <p>
        然后浏览器f12控制台输入document.cookie,例如:
    </p>

    <p>
        GSESSIONID=B8209EC9AF980BDFE89CF0C43C356DC8
    </p>

    <p> 
        则把B8209EC9AF980BDFE89CF0C43C356DC8复制到框内提交
    </p>
    <form action="evaluate" method="post">
        <input type="text" id="cookie" name="Mycookie">
        <input type="submit" id="btn_click" name="submit"/>
    </form>
    </body>

    </html>`
    ctx.body = html

})

home.post('/evaluate',async(ctx)=>{
    cookie = ctx.request.body.Mycookie;
    ctx.body = "[+]waiting..后台正在帮您自动评教..请一分钟以后刷新jwc查看情况...";
    console.log(cookie);
    autoFound('http://210.41.225.2/eams/quality/stdEvaluate.action',cookie);
})

app.use(bodyParser())
app.use(home.routes()).use(home.allowedMethods());
app.listen(3000)
console.log('[demo] start-quick is starting at port 3000')

如果想改变对老师的印象可自行更改以下内容

['老师真好,我很喜欢跟他相处','老师工作认真负责,课后问题及时讲解','在老师的课堂上学到很多知识']

应用实例2-XSSBOT

const flag = 'zer0pts{<censored>}';

// (snipped)

const crawl = async (url) => {
    console.log(`[+] Query! (${url})`);
    const page = await browser.newPage();
    try {
        await page.setUserAgent(flag);
        await page.goto(url, {
            waitUntil: 'networkidle0',
            timeout: 10 * 1000,
        });
        await page.click('#like');
    } catch (err){
        console.log(err);
    }
    await page.close();
    console.log(`[+] Done! (${url})`)
};
not found!