首页
社区
课程
招聘
[原创]对钉钉课堂邀请用户上台发言功能的逆向及成果利用
发表于: 2021-9-25 18:11 40273

[原创]对钉钉课堂邀请用户上台发言功能的逆向及成果利用

2021-9-25 18:11
40273

背景:钉钉开启课堂模式上课时,不能够批量邀请用户上台发言(下图所示),只能一个个点“邀请上台”按钮,给上课老师带来了极大的烦恼,为了优化用户体验,请给钉钉加上一键邀请学生上台发言的功能。

目标任务:完成钉钉课堂一键邀请上台功能、自动邀请上台功能

布置人:钱林松老师

作者:Cr39班 0xc5

软件版本:钉钉PC版本:6.0.26-Release.9039987

调试工具:x64Dbg Cheat Engine 7.0

  已知信息:课堂直播的进程名:tblive.exetvlive.exe是钉钉主进程DingTalk.exe的子进程。

  开启在线课堂,并使用x64dbgtblive.exe进行附加,发现tblive.exe运行过程中会输出许多调试字符串,判定为程序执行过程中输出的调试信息。

  笔者原先思路是对发包函数(sendto,end,WSASend,WSASendTo)下断点通过栈回溯找到关键CALL,现在转变思路,分析程序输出的调试信息,试图寻找关键的位置

  笔者一一调用上课及邀请同学上台等功能,分析输出的调试字符串,发现了可疑的信息

重点关注这一条调试信息

此条日志输出后,继续出现了下列添加、移除成员的调试信息

  根据上述添加成员、移除成员的调试信息,笔者猜测,这可能是邀请成员上台的相关内容,大胆猜测classroom_id为教室的门牌号,uids为邀请成员的编号。合理猜测,钉钉是通过SendMsg的方式将classroom_iduids转发到server,由server根据MsgNum统一处理消息。

​ 因此,全局搜索字符串“SendMsg”,搜索到如下位置

​ 对两处下软件断点,再次点击邀请上台,第二处断点成功断下。

​ 对上述反汇编代码进行分析,call <classroom.blog>是输出调式信息的函数,其参数分别是 eax,ecx,esi,依次对应Retcode,msg,msgNumbereax作为Retcode来源于call edx 这一间接调用中,猜测可能是发包函数,在call edx 处下软件断点。重新邀请成员上台,断点命中如下图所示!

笔者对该CALL参数进行分析,对参数分析如下

寄存器来源:

​ 1.eax:指向数据包ANSI字符串的指针。

​ 2.edi:固定值0x7cf

​ 3.edx:调用的发包函数地址,在ipcclient.dll 0x2f20偏移处,

​ 4.ecx:通过使用CE的指针扫描器进行扫描,得出其值是[[classroom.dll+0x53fc04]+4]

​ 笔者通过之前的分析,已经明确该调用该CALL所需的参数,针对邀请数据包的构造,还需要两个参数classroom_IDUser_ID ,即可构造数据包

​ 笔者通过不断的查看调用堆栈进行分析,最后找到下面这个位置

​ 继续分析,ecx来源于上一层调用后的eax的值,即call classroom.2766098的返回值,通过分析,最终确认 ClassRoom_ID 来源于 [classroom.dll + 0x542fB4]+c

​ 笔者通过栈回溯发现User_ID在动态存储的,只要台下学生列表刷新,其存储位置就会被释放然后重新分配内存存储,给获取带来一定的困难,因此笔者另辟蹊径,重新从日志寻找线索。

​ 笔者继续从输出的调试信息入手,经过反复测试,发现了上面的这一条关键性的日志。通过调试信息的内容推测是台下在线用户的信息,成功获取User_ID

​ 至此,调用发包函数Call edx的参数已经准备完毕,笔者使用CE的自动汇编功能进行测试。

​ 通过动态获取的Classroom_idUser_ID 构造邀请数据包,并使用CE在tblive.exe动态分配128字节内存,写入数据包信息

​ 然后使用CE自动汇编功能调用邀请call

​ 执行自动汇编脚本,成功邀请用户上台如下图:

​ 由之前的分析可知,若要实现自动邀请/一键邀请用户上台发言的功能,则必不可少的就是邀请的用户的User_ID列表。

​ 笔者通过不断的进入课堂,发现每当新用户进入时,tblive.exe会输出下列表示信息

​ 调试信息中就包含有User_ID等信息。

​ 笔者再次通过搜索字符串(LOW,但是在这里有效)的方法,定位输出调试字符串的位置。

​ 通过对此处进行InlineHook,即可获得User_ID,具体代码就不贴了,思路如下:

1.注入DLL,获取调用邀请CALL的所有参数信息

2.在tblive.exe进程内申请合适的内存用于存放邀请数据包的信息及执行邀请CALL的反汇编代码,并将相关反汇编代码拷贝到申请的内存中。

3.在上图处通过inlinehook获取user_id;存放到数据结构中;并使用Classroom_IDUser_ID构造邀请数据包,将其作为参数传入构造好的邀请CALL中,即可实现自动邀请用户上台发言的功能。

4.一键邀请上台功能的实现:在步骤3中,已存好每次进入课堂的User_ID,只需遍历该数据结构,构造邀请数据包,不断调用邀请CALL即可实现一键上台。

 
 
 
 
 
 
 
//下面是程序输出的部分调试信息。
调试字符串: "OnEvent code:11200, module:audio_energy, desc:, attribute:{"duration":5876,"playCallbacks":320,"playDuration":5876,"playLevel":1,"playMs":3199,"playRate":26140,"playSamples":153600,"recCallbacks":322,"recDuration":5876,"recLevel":99,"recMs":5897,"recRate":26304,"recSamples":154560}"
调试字符串: "OnEvent code:14002, module:ice_connection, desc:ice_network_interface_detected, attribute:{"Cellular":false,"Wifi":false,"any":false,"many":false,"relay":false,"sessionid":"315298512524207800","vpn":false}"
调试字符串: "OnEvent code:14002, module:ice_connection, desc:ice_network_interface_detected, attribute:{"Cellular":false,"Wifi":false,"any":false,"many":false,"relay":false,"sessionid":"774674212781047000","vpn":false}"
调试字符串: "SendMsg: 1405, {"classroom_id":"61489d302bb1d501588adde0","uids":[2120974346]}, retCode:1"
调试字符串: "conf OnMcsEvent  code:14007, msg:ice_connection_stats"
调试字符串: "conf OnMcsEvent  code:14007, msg:ice_connection_stats"
调试字符串: "conf OnMcsEvent  code:11200, msg:"
调试字符串: "conf OnMcsEvent  code:14002, msg:ice_network_interface_detected"
调试字符串: "conf OnMcsEvent  code:14002, msg:ice_network_interface_detected"
调试字符串: "OnAppInactive"
调试字符串: "OnChannelMsgFromServer: 1999, {"cmd":101,"body":"{\"conference_id\":\"61489d302bb1d501588adde0\",\"user_id\":\"2120974346\",\"nick\":\"sun\",\"ext_info\":\"\",\"role\":0,\"attend_status\":2,\"sub_status\":0,\"reject_description\":\"\",\"camera_status\":0,\"mic_status\":0,\"device_id\":\"X6tfdhCQZrMDAMVSGCCYhOPr\",\"start_timestamp\":0,\"record_status\":0,\"uid_domain\":\"DingTalk\",\"pdp_code\":0,\"protocol\":\"webrtc\",\"device_type\":\"\",\"sip_uid\":\"\",\"sip_pid\":\"\"}"}"
调试字符串: "OnIpcConfMemberChanged, {"conference_id":"61489d302bb1d501588adde0","user_id":"2120974346","nick":"sun","ext_info":"","role":0,"attend_status":2,"sub_status":0,"reject_description":"","camera_status":0,"mic_status":0,"device_id":"X6tfdhCQZrMDAMVSGCCYhOPr","start_timestamp":0,"record_status":0,"uid_domain":"DingTalk","pdp_code":0,"protocol":"webrtc","device_type":"","sip_uid":"","sip_pid":""}"
调试字符串: "RemoveJoinedMember, uid=2120974346"
调试字符串: "RemoveJoinedMember, uid=2120974346 not exist"
调试字符串: "AddUnjoinedMember, uid=2120974346"
调试字符串: "AddUnjoinedMember, uid=2120974346 already exist"
调试字符串: "ConfMgr::OnParticipantJoined, origin:61489efa2bb1d501588d95e0, uid=2120974346"
调试字符串: "ConfMgr::OnParticipantJoined no remote stream to add to map, participant_id:61489efa2bb1d501588d95e0, uid:2120974346"
调试字符串: "INFO: add observer for participant:61489efa2bb1d501588d95e0"
调试字符串: "Invalid parameter passed to C runtime function."
//下面是程序输出的部分调试信息。
调试字符串: "OnEvent code:11200, module:audio_energy, desc:, attribute:{"duration":5876,"playCallbacks":320,"playDuration":5876,"playLevel":1,"playMs":3199,"playRate":26140,"playSamples":153600,"recCallbacks":322,"recDuration":5876,"recLevel":99,"recMs":5897,"recRate":26304,"recSamples":154560}"
调试字符串: "OnEvent code:14002, module:ice_connection, desc:ice_network_interface_detected, attribute:{"Cellular":false,"Wifi":false,"any":false,"many":false,"relay":false,"sessionid":"315298512524207800","vpn":false}"
调试字符串: "OnEvent code:14002, module:ice_connection, desc:ice_network_interface_detected, attribute:{"Cellular":false,"Wifi":false,"any":false,"many":false,"relay":false,"sessionid":"774674212781047000","vpn":false}"
调试字符串: "SendMsg: 1405, {"classroom_id":"61489d302bb1d501588adde0","uids":[2120974346]}, retCode:1"
调试字符串: "conf OnMcsEvent  code:14007, msg:ice_connection_stats"
调试字符串: "conf OnMcsEvent  code:14007, msg:ice_connection_stats"
调试字符串: "conf OnMcsEvent  code:11200, msg:"
调试字符串: "conf OnMcsEvent  code:14002, msg:ice_network_interface_detected"
调试字符串: "conf OnMcsEvent  code:14002, msg:ice_network_interface_detected"
调试字符串: "OnAppInactive"
调试字符串: "OnChannelMsgFromServer: 1999, {"cmd":101,"body":"{\"conference_id\":\"61489d302bb1d501588adde0\",\"user_id\":\"2120974346\",\"nick\":\"sun\",\"ext_info\":\"\",\"role\":0,\"attend_status\":2,\"sub_status\":0,\"reject_description\":\"\",\"camera_status\":0,\"mic_status\":0,\"device_id\":\"X6tfdhCQZrMDAMVSGCCYhOPr\",\"start_timestamp\":0,\"record_status\":0,\"uid_domain\":\"DingTalk\",\"pdp_code\":0,\"protocol\":\"webrtc\",\"device_type\":\"\",\"sip_uid\":\"\",\"sip_pid\":\"\"}"}"
调试字符串: "OnIpcConfMemberChanged, {"conference_id":"61489d302bb1d501588adde0","user_id":"2120974346","nick":"sun","ext_info":"","role":0,"attend_status":2,"sub_status":0,"reject_description":"","camera_status":0,"mic_status":0,"device_id":"X6tfdhCQZrMDAMVSGCCYhOPr","start_timestamp":0,"record_status":0,"uid_domain":"DingTalk","pdp_code":0,"protocol":"webrtc","device_type":"","sip_uid":"","sip_pid":""}"
调试字符串: "RemoveJoinedMember, uid=2120974346"
调试字符串: "RemoveJoinedMember, uid=2120974346 not exist"
调试字符串: "AddUnjoinedMember, uid=2120974346"
调试字符串: "AddUnjoinedMember, uid=2120974346 already exist"
调试字符串: "ConfMgr::OnParticipantJoined, origin:61489efa2bb1d501588d95e0, uid=2120974346"
调试字符串: "ConfMgr::OnParticipantJoined no remote stream to add to map, participant_id:61489efa2bb1d501588d95e0, uid:2120974346"
调试字符串: "INFO: add observer for participant:61489efa2bb1d501588d95e0"
调试字符串: "Invalid parameter passed to C runtime function."
调试字符串: "SendMsg: 1405, {"classroom_id":"61489d302bb1d501588adde0","uids":[2120974346]}, retCode:1"
调试字符串: "SendMsg: 1405, {"classroom_id":"61489d302bb1d501588adde0","uids":[2120974346]}, retCode:1"
调试字符串: "RemoveJoinedMember, uid=2120974346"
调试字符串: "RemoveJoinedMember, uid=2120974346 not exist"
调试字符串: "AddUnjoinedMember, uid=2120974346"
调试字符串: "AddUnjoinedMember, uid=2120974346 already exist"
调试字符串: "RemoveJoinedMember, uid=2120974346"
调试字符串: "RemoveJoinedMember, uid=2120974346 not exist"
调试字符串: "AddUnjoinedMember, uid=2120974346"
调试字符串: "AddUnjoinedMember, uid=2120974346 already exist"
 
 
;以下是第二处断点的上下文反汇编
lea ecx,dword ptr ss:[ebp-44]
mov byte ptr ss:[ebp-4],1
call classroom.2CC16FE
mov edi,dword ptr ss:[ebp-60]
mov ecx,dword ptr ss:[ebp-64]
cmp dword ptr ss:[ebp-14],10
mov ecx,dword ptr ds:[ecx+4]
mov eax,dword ptr ds:[ecx]
mov edx,dword ptr ds:[eax]
lea eax,dword ptr ss:[ebp-28]
cmovae eax,dword ptr ss:[ebp-28]
push eax
push edi
call edx
cmp esi,1FE
je classroom.2D59C47
cmp esi,34F
je classroom.2D59C47
cmp esi,354
je classroom.2D59C47
cmp esi,7D0
je classroom.2D59C47
cmp esi,4B1
je classroom.2D59C47
cmp dword ptr ss:[ebp+20],10
lea ecx,dword ptr ss:[ebp+C]
movzx eax,al
cmovae ecx,dword ptr ss:[ebp+C]
push eax
push ecx
push esi
push classroom.2FDCC30            ;SendMsg字符串
push 12C
call <classroom.blog>            ;输出日志函数
add esp,14
;以下是第二处断点的上下文反汇编
lea ecx,dword ptr ss:[ebp-44]
mov byte ptr ss:[ebp-4],1
call classroom.2CC16FE
mov edi,dword ptr ss:[ebp-60]
mov ecx,dword ptr ss:[ebp-64]
cmp dword ptr ss:[ebp-14],10
mov ecx,dword ptr ds:[ecx+4]
mov eax,dword ptr ds:[ecx]
mov edx,dword ptr ds:[eax]
lea eax,dword ptr ss:[ebp-28]
cmovae eax,dword ptr ss:[ebp-28]
push eax
push edi
call edx
cmp esi,1FE
je classroom.2D59C47

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2021-9-25 22:28 被0xC5编辑 ,原因:
收藏
免费 14
支持
分享
打赏 + 5.00雪花
打赏次数 1 雪花 + 5.00
 
赞赏  Imyang   +5.00 2021/09/26 感谢分享~
最新回复 (9)
雪    币: 2745
活跃值: (1846)
能力值: ( LV12,RANK:298 )
在线值:
发帖
回帖
粉丝
2
棒!
2021-9-26 14:09
0
雪    币: 3297
活跃值: (5395)
能力值: ( LV6,RANK:92 )
在线值:
发帖
回帖
粉丝
3
KuCha128 棒!
感谢夸奖
2021-9-26 16:34
0
雪    币: 638
活跃值: (1772)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
4
伟大的逆向攻城狮, 官方不做的, 我们就自食其力。 彩~
2021-9-26 16:57
0
雪    币: 1051
活跃值: (941)
能力值: ( LV3,RANK:35 )
在线值:
发帖
回帖
粉丝
5
学习了
2021-9-26 22:10
0
雪    币: 6092
活跃值: (704)
能力值: ( LV4,RANK:45 )
在线值:
发帖
回帖
粉丝
6
很不错
2021-9-27 09:29
0
雪    币: 168
活跃值: (550)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
学习了
2021-10-4 14:57
0
雪    币: 4880
活跃值: (2544)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
思路很清晰,分析很到位,学习了,感谢分享!
2021-10-6 09:06
0
雪    币: 143
活跃值: (861)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
逆向需要灵感及毅力
2021-10-6 14:11
0
雪    币: 215
活跃值: (119)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
牛!
2022-2-23 15:27
0
游客
登录 | 注册 方可回帖
返回
//