抓包某PMP培训机构APP并下载所有PMP课程

(编辑:jimmy 日期: 2024/12/24 浏览:2)


前言
3年前报考了PMP,疫情原因推迟两年没考,近期通知6.25要考试了,临时抱佛脚赶快刷视频。
前年的时候也抓包把所有课程打包下了一次,但是现在PMP改版,之前的视频已经过时了,在线看的又不方便,所以又重新抓包下载,这次把过程和代码记录下来。
【备注】
PMP的考试是必须通过这种培训机构才可以报名考试的,即便你看了视频,想要考试,还是得先找机构报名,才能考试。
另外,抓包下载课程的前提条件还是必须得先买了课程才可以看到内容。
把下载的视频分享出来主要是出于大家一起学习项目管理。
使用到的工具:
【雷电3.0】【某环APP】【Charles抓包】
开发语言:
Java
步骤
1、安装Charles,开启代{过}{滤}理,设置https证书
这一步论坛或者百度一下很多教程,比如:搜索 - 吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn ,这里就不细讲了。
抓包某PMP培训机构APP并下载所有PMP课程

1.png


抓包某PMP培训机构APP并下载所有PMP课程

Charles 4.2.7 - Sess_2022-05-31_16-37-46.png


2、安装雷电3.0模拟器
使用3.0的主要原因是抓包需要安装并信任https证书,安卓高版本好像没办法,所以用的是雷电3.0。
安装好之后设置网络桥接,安装驱动;
抓包某PMP培训机构APP并下载所有PMP课程

Snipper - Snipaste_2022-05-31_13-27-18.png


打开雷电之后,进入wlan设置,长按,修改网络,进入高级选项,打开代{过}{滤}理,设置为Charles代{过}{滤}理的IP+端口
抓包某PMP培训机构APP并下载所有PMP课程

雷电模拟器_2022-05-31_13-27-50.png


抓包某PMP培训机构APP并下载所有PMP课程

2225.png


3、安装某环APP,进入我的学习开始抓包
这里要吐槽一下APP的开发了,获取用户信息的接口没有任何登录鉴权,随便传个userid就可以获取该用户的邮箱 手机信息,借此其实可以轮询到所有的用户隐私信息。
抓包某PMP培训机构APP并下载所有PMP课程

Charles 4.2.7 - Sess_2022-05-31_16-37-25.png


言归正传,说下怎么获取所有的课程
这里通过点击APP,发现需要通过4个步骤
[Java] 纯文本查看 复制代码
static String url1 = "https://app.xxxx.com/Lesson/myLessons";// 1、获取班级地址static String url2 = "https://app.xxxx.com/User/myLesson";// 2、获取课程地址static String url3 = "https://app.xxxx.com/Lesson/detail";// 3、获取课程列表static String url4 = "https://app.xxxx.com/Lesson/play";// 3、获取课程文件

每次请求传入的参数基本就是上一个接口返回的id,
所以代码逻辑就是
1、获取用户获取到该用户的班级列表
2、根据班级获取到班级内的课程
3、获取课程内的在线课程
4、根据在线课程获取课程的视频文件或者课程作业
5、多线程下载文件
下面是具体代码,时间有限,也没有做什么规范和优化,凑合看下吧
[Java] 纯文本查看 复制代码
public class Test {        static String filePath = "E:\\下载\\PMP"; //保存路径        static String userid = "xxxx";//抓包从请求头获取        static String url1 = "https://app.xxxx.com/Lesson/myLessons";// 1、获取班级地址        static String url2 = "https://app.xxxx.com/User/myLesson";// 2、获取课程地址        static String url3 = "https://app.xxxx.com/Lesson/detail";// 3、获取课程列表        static String url4 = "https://app.xxxx.com/Lesson/play";// 3、获取课程文件        static Map<String, String> headMap = new HashMap<String, String>();        public static void main(String[] args) throws Exception {                List<String[]> tempmap = new ArrayList();                filePath += new Random(10000).nextLong() + "\\";                headMap.put("secket", "xxxxx");//抓包从请求头获取                headMap.put("apid", "yun.aura.cn");                headMap.put("Content-Type", "application/json;charset=UTF-8");                System.out.println("获取班级列表");                String result = SdkClient.post(url1 + "?p=1&uid=" + userid, "", headMap);                System.out.println(result);                if (result != null && !"".equals(result) && result.contains("userInfo")) {                        JSONObject myLessonsresult = JSON.parseObject(result);                        JSONArray data = myLessonsresult.getJSONArray("data");                        for (int i = 0; i < data.size(); i++) {                                JSONObject o = data.getJSONObject(i);                                String LessonID = o.getString("lesson_id");                                String LessonName = o.getString("name");                                String current_filePath1 = filePath + LessonName + "\\";                                System.out.println("创建班级目录:" + current_filePath1);                                new File(current_filePath1).mkdirs();                                System.out.println("获取班级课程,id=" + LessonID);                                result = SdkClient.post(url2 + "?lid=" + LessonID + "&uid=" + userid, "", headMap);                                System.out.println(result);                                if (result != null && !"".equals(result) && result.contains("success")) {                                        JSONObject myLessonsresult2 = JSON.parseObject(result);                                        JSONArray data2 = myLessonsresult2.getJSONObject("data").getJSONArray("data");                                        for (int i2 = 0; i2 < data2.size(); i2++) {                                                JSONObject o2 = data2.getJSONObject(i2);                                                String LessonID2 = o2.getString("lid");                                                String LessonName2 = o2.getString("name");                                                String current_filePath2 = current_filePath1 + (i2 < 9 ? ("0" + (i2 + 1)) : (i2 + 1)) + " "                                                                + LessonName2 + "\\";                                                System.out.println("创建课程目录:" + current_filePath2);                                                new File(current_filePath2).mkdirs();                                                System.out.println("获取课程文件列表,lid=" + LessonID2);                                                result = SdkClient.post(                                                                url3 + "?pkid=" + LessonID + "&id=" + LessonID2 + "&teach_type=2" + "&uid=" + userid,                                                                "", headMap);                                                System.out.println(result);                                                if (result != null && !"".equals(result) && result.contains("Hello world")) {                                                        JSONObject myLessonsresult3 = JSON.parseObject(result);                                                        JSONArray catalogues = myLessonsresult3.getJSONArray("catalogue");                                                        for (int i3 = 0; i3 < catalogues.size(); i3++) {                                                                JSONObject catalogue = catalogues.getJSONObject(i3);                                                                String catalogueName = catalogue.getString("name");                                                                String current_filePath3 = current_filePath2 + (i3 < 9 ? ("0" + (i3 + 1)) : (i3 + 1))                                                                                + " " + catalogueName + "\\";                                                                System.out.println("创建课程文件目录:" + current_filePath3);                                                                new File(current_filePath3).mkdirs();                                                                JSONArray catalogues_childrens = catalogue.getJSONArray("children");                                                                for (int i4 = 0; i4 < catalogues_childrens.size(); i4++) {                                                                        JSONObject catalogues_children = catalogues_childrens.getJSONObject(i4);                                                                        String catalogues_childrenName = catalogues_children.getString("name");                                                                        String current_filePath4 = current_filePath3 + " "                                                                                        + (i4 < 9 ? ("0" + (i4 + 1)) : (i4 + 1)) + catalogues_childrenName + "\\";                                                                        System.out.println("创建课程文件二级目录:" + current_filePath4);                                                                        new File(current_filePath4).mkdirs();                                                                        JSONArray catalogues_childrens_too = catalogues_children.getJSONArray("children");                                                                        for (int i5 = 0; i5 < catalogues_childrens_too.size(); i5++) {                                                                                JSONObject kecheng = catalogues_childrens_too.getJSONObject(i5);                                                                                String sort = kecheng.getString("sort");                                                                                String playurl = url4 + "?pkid=" + LessonID + "&id=" + LessonID2 + "&sid="                                                                                                + sort + "&teach_type=2" + "&uid=" + userid;                                                                                result = SdkClient.post(playurl, "", headMap);                                                                                if (result != null && !"".equals(result) && result.contains("Hello world")) {                                                                                        JSONObject fileinfo = JSON.parseObject(result);                                                                                        fileinfo = fileinfo.getJSONObject("data");                                                                                        String fileinfoName = fileinfo.getString("kj_name");                                                                                        String fileinfoUrl = fileinfo.getString("aliInfo");                                                                                        System.out.println("创建课程文件:" + current_filePath4 + fileinfoName);                                                                                        System.out.println(fileinfoUrl);                                                                                        File urltxt = new File(current_filePath4 + "url.txt");                                                                                        urltxt.createNewFile();                                                                                        FileUtil.appendString(urltxt, fileinfoUrl);                                                                                        tempmap.add(new String[] { fileinfoUrl, current_filePath4 + fileinfoName });                                                                                }                                                                        }                                                                }                                                        }                                                }                                        }                                }                                System.out.println("开启多线程下载");                                ExecutorService threadPool = Executors.newCachedThreadPool();                                int threadCount = 5;                                int threadTaskCount = tempmap.size() / 5;                                System.out.println(                                                "共开启" + threadCount + "条线程,预计下载文件" + tempmap.size() + "个,每条线程下载" + threadTaskCount + "个文件");                                CountDownLatch latch = new CountDownLatch(threadCount);                                List<String[]> urls = new ArrayList();                                for (int iii = 0; iii < tempmap.size(); iii++) {                                        String[] url = tempmap.get(iii);                                        urls.add(url);                                        if (iii % threadTaskCount == 0 || iii == tempmap.size() - 1) {                                                QueryTask task = new QueryTask(urls, latch);                                                threadPool.execute(task);                                                urls = new ArrayList();                                        }                                }                                // 等待线程池中的线程全部执行完毕                                latch.await();                                // 关闭线程池                                threadPool.shutdown();                        }                }        }}class QueryTask implements Runnable {        private List<String[]> urls;        private CountDownLatch latc;        public QueryTask() {                super();        }        public QueryTask(List<String[]> urls, CountDownLatch latc) {                super();                this.urls = urls;                this.latc = latc;        }        // 下载链接 下载到的目录 下载后的文件名称        public static boolean download(String urlPath, String fileName) throws Exception {                // 解决url中可能有中文情况                URL url = new URL(urlPath);                HttpURLConnection http = (HttpURLConnection) url.openConnection();                http.setConnectTimeout(3000);                // 设置 User-Agent 避免被拦截                http.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)");                // 获取文件名                InputStream inputStream = http.getInputStream();                byte[] buff = new byte[1024 * 10];                File file = new File(fileName);                if (!file.exists()) {                        OutputStream out = new FileOutputStream(file);                        int len;                        int count = 0; // 计数                        while ((len = inputStream.read(buff)) != -1) {                                out.write(buff, 0, len);                                out.flush();                                ++count;                        }                        // 关闭资源                        out.close();                        inputStream.close();                        http.disconnect();                        return true;                }                return false;        }        @Override        public void run() {                try {                        for (String[] u : urls) {                                download(u[0], u[1]);                        }                } catch (Exception e) {                        e.printStackTrace();                } finally {                        // 每结束一个线程,就要总数减一                        latc.countDown();                }        }}

最后所有的文件也会按照目录生成
抓包某PMP培训机构APP并下载所有PMP课程

snipaste_20220531_134728.png


最终结果我上传到网盘了,见附件。

一句话新闻

一文看懂荣耀MagicBook Pro 16
荣耀猎人回归!七大亮点看懂不只是轻薄本,更是游戏本的MagicBook Pro 16.
人们对于笔记本电脑有一个固有印象:要么轻薄但性能一般,要么性能强劲但笨重臃肿。然而,今年荣耀新推出的MagicBook Pro 16刷新了人们的认知——发布会上,荣耀宣布猎人游戏本正式回归,称其继承了荣耀 HUNTER 基因,并自信地为其打出“轻薄本,更是游戏本”的口号。
众所周知,寻求轻薄本的用户普遍更看重便携性、外观造型、静谧性和打字办公等用机体验,而寻求游戏本的用户则普遍更看重硬件配置、性能释放等硬核指标。把两个看似难以相干的产品融合到一起,我们不禁对它产生了强烈的好奇:作为代表荣耀猎人游戏本的跨界新物种,它究竟做了哪些平衡以兼顾不同人群的各类需求呢?