2024-10-27-【记录】内网使用p4wnp1传递文件.md 12 KB


title: 【记录】内网使用P4wnP1传递文件 urlname: internal-network-uses-p4wnp1-to-transfer-file index_img: https://api.limour.top/randomImg?d=2024-10-27 07:05:01 date: 2024-10-27 15:05:01

tags: raspberrypi

最近实习轮转到预防了,需要在社区实习4周,而社区医生有一堆需要重复填报的数据,因此写了下面的脚本来自动化填写。而问题是社区的电脑禁用了U盘等设备的使用,因此想将这个脚本传递到其他电脑上只能手打一次。。。 于是想到的吃灰已久的树莓派zero w,给它刷上了 P4wnP1 ALOA 来模拟键盘输入,这样就不用手打了。 {% fold info @点开查看社区填报自动化脚本 %}

async function sleep(timeout) {
    await new Promise((resolve)=>{
        setTimeout(resolve, timeout * 1000);
    }
    );
}
;async function processRows() {

    for (let i = 0; i <= 29; i++) {

        var orignialWindowOpen = window.open;
        window.open = async function() {
            var taskid = i + 1
            var newWindow = orignialWindowOpen.apply(this, arguments);
            await sleep(1);
            // var newWindow = window;  //调试用
            // console.log("newWindow ", newWindow);
            // 100s 强制关闭
            setTimeout(()=>{
                if (!newWindow.closed) {
                    newWindow.close();
                    console.log("Manipulating Row", taskid, "Window closed at 100s");
                }
            }
            , 100000);

            var alerted = false;
            newWindow.confirm = (m)=>console.log('confirm', taskid, m);
            newWindow.alert = (m)=>{
                console.log('alert', taskid, m);
                alerted = true;
            }

            var isElLoaded = async sl=>{
                await sleep(0.05);
                if (newWindow.closed) {
                    throw taskid + "newWindow.closed"
                }
                while (newWindow.document.querySelector(sl) === null) {
                    await new Promise((resolve)=>{
                        requestAnimationFrame(resolve)
                    }
                    );
                }
                ;return newWindow.document.querySelector(sl);
            }
            ;
            function rrrand(min, max) {
                return Math.floor(Math.random() * (max - min + 1)) + min
            }
            ;function setValue(el, min, max) {
                if (!el || !el.value) {
                    el.value = rrrand(min, max).toFixed(1);
                }
            }
            ;await sleep(0.5);

            taskid = (await isElLoaded("#Name")).value + ' ' + taskid;

            (await isElLoaded("#d1 > div.fieldset1 > fieldset > div > div > label:nth-child(1) > input")).checked = true;
            (await isElLoaded("#d1 > div.fieldset15 > fieldset > div > div > label:nth-child(1) > input")).checked = true;

            (await isElLoaded("#d1 > div.fieldset3 > fieldset > legend > span.title_icon.plus_icon")).click();
            await sleep(1);
            (await isElLoaded("#d1 > div.fieldset3 > fieldset > div:nth-child(2) > div:nth-child(2) > div > label:nth-child(4) > input[type=radio]")).click();
            await sleep(0.3);
            (await isElLoaded("#d1 > div.fieldset3 > fieldset > div:nth-child(3) > div > label:nth-child(1) > input[type=radio]")).click();
            await sleep(0.3);
            (await isElLoaded("#d1 > div.fieldset3 > fieldset > div:nth-child(4) > div:nth-child(2) > div > label:nth-child(1) > input[type=radio]")).click();
            await sleep(0.3);
            (await isElLoaded("#yjqk")).click();
            await sleep(0.3);

            (await isElLoaded("#d1 > div.fieldset4 > fieldset > div:nth-child(2) > div > label:nth-child(1) > input")).checked = true;
            (await isElLoaded("#d1 > div.fieldset4 > fieldset > div:nth-child(3) > div > label:nth-child(1) > input")).checked = true;
            (await isElLoaded("#d1 > div.fieldset4 > fieldset > div:nth-child(4) > div > label:nth-child(1) > input")).checked = true;
            (await isElLoaded("#d1 > div.fieldset4 > fieldset > div:nth-child(5) > div > label:nth-child(1) > input")).checked = true;
            (await isElLoaded("#d1 > div.fieldset4 > fieldset > div:nth-child(6) > div > label:nth-child(1) > input")).checked = true;
            (await isElLoaded("#d1 > div.fieldset4 > fieldset > div:nth-child(7) > div > label:nth-child(1) > input")).checked = true;

            (await isElLoaded("#d1 > div.fieldset4 > fieldset > div:nth-child(8) > div > label:nth-child(1) > input[type=radio]")).click();
            await sleep(0.3);
            (await isElLoaded("#d1 > div.fieldset4 > fieldset > div:nth-child(9) > div > label:nth-child(1) > input[type=radio]")).click();
            await sleep(0.3);

            var sg = await isElLoaded("#sg");
            var tz = await isElLoaded("#tz");
            var yw = await isElLoaded("#yw");
            var age = await isElLoaded("#Age");
            var gender = await isElLoaded("#Gender");
            var xy1 = await isElLoaded("#xy1");
            var xy2 = await isElLoaded("#xy2");
            var isHypertension = (await isElLoaded('#d1 > div.fieldset1 > fieldset > div > div > label:nth-child(2) > input[type=checkbox]')).checked
            console.log(taskid, 'isHypertension', isHypertension)

            setValue(xy1, 110, 130);
            setValue(xy2, 75, 85);

            if (gender.value == '男') {
                setValue(sg, 165, 180);
                setValue(tz, 60, 80);
            } else {
                setValue(sg, 150, 170);
                setValue(tz, 50, 70);
            }
            ;var sgv = parseFloat(sg.value);
            var tzv = parseFloat(tz.value);
            var bmi = tzv / (sgv * sgv / 10000);
            var bzyw = sgv * bmi / 50;
            setValue(yw, bzyw, bzyw);

            (await isElLoaded("#span_btn_save")).click();

            while (!(await isElLoaded("#jjkzdqt")).value) {
                await sleep(1);
            }
            console.log(taskid, (await isElLoaded("#jjkzdqt")).value);

            (await isElLoaded("#A6")).click();
            console.log(taskid, alerted);
            alerted = false;
            while (!alerted) {
                await sleep(1);
            }
            (await isElLoaded("#sp3")).click();
            await sleep(2);
            (await isElLoaded("#span_btn_Scheme > a")).click();
            while ((await isElLoaded("#YXFAMAIN")).children.length < 2) {
                await sleep(1);
            }
            (await isElLoaded("#div_spn > span.buttons.btn_save6 > a")).click();

            console.log(taskid, '已选方案数量:', (await isElLoaded("#SchemeList > div")).children.length)
            newWindow.close();
            console.log("Manipulating Row", taskid, "Window closed");
            return newWindow;
        }

        console.log("Manipulating Row", i + 1);
        var currentRow = document.querySelector(`#dgvResult_${i}`);
        currentRow.click();
        showForm('ibtnUserDefine', 1);
        await sleep(30);

        window.focus();
        window.open = orignialWindowOpen;
    }
    ;
}
;async function limour_main() {
    while (true) {
        await processRows();
        document.querySelector("#QueryButton1_LinkButton1").click();
        await sleep(35);
    }
}
;limour_main()

{% endfold %}

准备工作

写入镜像的教程很多,就不赘述了,先格式化SD卡,然后写入.img文件就行

连接树莓派

  • 树莓派zero w 的带 USB 标志的口通过手机数据线连接到靶机上,PWR口不用管
  • 等待一个 P4WNp1 的 WIFI,连接它,密码是 MaMe82-P4wnP1,此时IP为 172.24.0.1
  • 或者也可以搜索一个P4wnP1的蓝牙,连接它,默认PIN是 1337,然后加入蓝牙个人区域网,此时IP为 172.26.0.1
  • 然后可以ssh连接对应的IP,默认用户名root,密码toor

配置 USB

  • 访问 http://172.24.0.1:8000/ (蓝牙就算了,太慢了打不开)
  • 此时靶机会有一个驱动错误的提示,我们需要将 USB Gadget Settings 中的 CDC ECMRNDIS 两项关闭
  • 只保留 KeyboardMouse 两项,然后点击 STOREDEPLOY STORED 后等一会,驱动错误提示就会消失了

测试 HIDScript

  • USB SETTINGS 转到 HIDScrip

    layout('us');			// 键盘布局
    typingSpeed(50,100);	// 敲击按键的时候等待的间隔100毫秒加上0-150毫秒之间的随机值
     
    press("GUI r");         //类似按下某个键位然后再抬起来,具体可以看官方文档,和上面的机制相识
    delay(500);             //暂停时间
    type("notepad\n");      //输入字符串,模拟键盘按键
    delay(1500);            //暂停时间
    // moveStepped(x,y);    //鼠标移动,相当于模拟正常运动
    // moveTo(x,y);         //鼠标移动到设置的坐标点,x和y分别是横纵坐标
    type("Hello from P4wnP1\n");
    
    typingSpeed(10,20);
    var base64 = 'SGVsbG8gZnJvbSBQNHduUDE=' // btoa('Hello from P4wnP1');
    type("atob('" + base64 + "');");
    

关闭树莓派

  • 不要直接拔电源,不然下次无法开机
  • ssh连接后输入 shutdown -h now
  • 等待 LED 灯闪烁熄灭,先别急,再等一会,会再次闪烁后熄灭
  • 此时可以安全拔掉数据线了

获取要模拟设备的信息

  • 下载 USBDeview
  • 将靶机的键盘插到自己电脑上,获取序列号VIDPID等信息,在 P4wnP1 中模拟

传递 client.html

  • 靶机输入法调成美式键盘
  • P4wnP1 上运行 HIDscript.js
  • 约 10 分钟后输入结束,此时将文件保存成 client.html
  • 靶机上用 chrome 打开 client.html
  • client.html 上选择要传递的文件,等待二维码开始变化

接收文件

  • 宿主机配置对应的环境后运行 server.py
  • 将摄像头对准动态的二维码
  • 待搜集足够多的包后,会自动解码,将文件保存到 qr.dl 中,重命名恢复文件
  • 摄像头推荐用 IP Webcam, 电脑连接手机热点即可。
  • IP Webcam 备份,使用 MT 管理器安装。

喷泉码说明

在编码理论中,喷泉码(也称为无码率抹除码)是一类抹除码,这种编码能够从一组给定的源符号序列中产生一串不限长度的编码符号序列,在理想情况下,从编码符号序列中获得大小和源符号相同或稍大的任意子集,便可恢复源符号。

  • 对喷泉码感兴趣的话,分别有 js 实现和 python 实现,可互相编解码。

传送文件

  1. 执行 HIDscript_save.js, 保存为 save.html
  2. 打开 read_as_HIDscript.html
  3. 选择要传递给靶机的文件,然后执行自动生成的 HIDscript
  4. 执行完毕后打开靶机上保存的 save.html, 将键盘输入的字符粘贴过去,点击转换就会将保存转换的文件