记一次钉钉自动签到

声明:只是为了学习追求技术的提升,如有侵权,请告知删除

使用条件

钉钉课程打卡

版本

钉钉5.0.12

钉钉5.0.15

其他版本敬请摸索

工具

xposed,Android Studio

开发基础

xposed.rimet

这个项目原是skywei的钉钉助手开源项目,我拿来重复造轮子,如有侵权,敬请告知。

注意!以下内容必须是有钉钉源码才能看得懂

ddms查看堆栈

本步略过。懒得截图了

追溯调用

可以找到 Interative_helper,这个类(是混淆过的,需要寻找代码)找到了ctw$a 这个instance。发现几乎所有的call都是这个instance,于是用xposedHelper得到这个instance

代码如下

 Class InterativeCardInternal= findClass(M.classz.class_defpackage_Interative_helper);
 Object InterativeCardInstance= XposedHelpers.getStaticObjectField(InterativeCardInternal,"a");

除此之外,还有一个cardInstanceId十分关键,直接通过message类调用它的子类实现getCardId。

        Object messageContent = XposedHelpers.callMethod(message,
                getXString(M.method.method_wukong_im_message_MessageImpl_messageContent));
        long cardId=(long)XposedHelpers.callMethod(messageContent,"getCardId");

获得的信息类似于下图args:

 还需要进行下一步转换,由于该项目没有JSON,于是直接饮用alibaba的fastjson

             Class ClassJSON=findClass(M.classz.class_com_alibaba_fastjson_JSON);
             Object Jobject= XposedHelpers.callStaticMethod(ClassJSON,"parseObject","{\"actionData\":{\"bizType\":\"1\"},\"actionId\":\"\",\"actionType\":\"0\",\"cardInstanceId\":\""+cardId+"\"}");

直接调用a方法,实现按钮点击

 

XposedHelpers.callMethod(InterativeCardInstance,"a",cardId,Jobject);

这一步实现了但是还没有结束,因为服务器是接收到了签到信息,事实上也是签到完成了,但是客户端没有及时处理这个消息。所以我们需要更新一下数据库,这里直接copy反撤回代码。

            Method methodMessageUpdate =  findMatcherMethod(
                    M.classz.class_defpackage_MessageDs,
                    M.method.method_defpackage_MessageDs_update,
                    String.class, String.class, List.class);

            Class classIMDatabase = findClass(M.classz.class_wukong_im_base_IMDatabase);

            String dbName = (String) XposedHelpers.callStaticMethod(classIMDatabase,
                    getXString(M.method.method_wukong_im_base_IMDatabase_getWritableDatabase));

            methodMessageUpdate.invoke(null, dbName, cid, Collections.singletonList(message));

完整代码

    private void handlerLessonMessage(String cid, Object message){

        if (!mEnableLesson)return;

        // 直接根据消息类型来处理
        Object messageContent = XposedHelpers.callMethod(message,
                getXString(M.method.method_wukong_im_message_MessageImpl_messageContent));
        long cardId=(long)XposedHelpers.callMethod(messageContent,"getCardId");

        try {
             Class InterativeCardInternal= findClass(M.classz.class_defpackage_Interative_helper);
             Object InterativeCardInstance= XposedHelpers.getStaticObjectField(InterativeCardInternal,"a");
             Class ClassJSON=findClass(M.classz.class_com_alibaba_fastjson_JSON);
             Object Jobject= XposedHelpers.callStaticMethod(ClassJSON,"parseObject","{\"actionData\":{\"bizType\":\"1\"},\"actionId\":\"\",\"actionType\":\"0\",\"cardInstanceId\":\""+cardId+"\"}");

             //Log.d("sky","InterativeCardGot");
             Log.d(TAG, "handlerLessonMessage: "+InterativeCardInstance.getClass().getName());

             XposedHelpers.callMethod(InterativeCardInstance,"a",cardId,Jobject);

            Method methodMessageUpdate =  findMatcherMethod(
                    M.classz.class_defpackage_MessageDs,
                    M.method.method_defpackage_MessageDs_update,
                    String.class, String.class, List.class);

            Class classIMDatabase = findClass(M.classz.class_wukong_im_base_IMDatabase);

            String dbName = (String) XposedHelpers.callStaticMethod(classIMDatabase,
                    getXString(M.method.method_wukong_im_base_IMDatabase_getWritableDatabase));

            methodMessageUpdate.invoke(null, dbName, cid, Collections.singletonList(message));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

这个handleLesson类似于skywei项目的

handlerLuckyMessage等函数,我只是加入了一个cid参数,这个在上一层可以获取。

最后

特别感谢skywei的钉钉助手项目,这个项目在我的github上有,有兴趣的朋友右上角fork me 进入我的github可以查看

posted @ 2020-05-06 19:56  Cross2Pro  阅读(477)  评论(0编辑  收藏  举报