本帖最后由 zjh16529 于 2019-6-6 18:23 编辑
前记 这仅仅是本人无聊至极做出的分析,至于编程,本人也只是小小菜鸟,如有不当请大牛指正,自当万分感激。 由于微机课总是被老师的一节课的长篇大论占用完,所以感到心中不服,特此找来了这个软件来把玩,看看能不能写出一个内存补丁,实现屏幕广播窗口化并且不使鼠标键盘被锁定。然而出师不利,找个样本太困难,网上几乎没有,总算找到,在虚拟机里面安装的时候却蓝屏很多次……(解决方法:在系统盘根目录下找到BOOT.INI(Windows XP)这个文件,而后修改第一条启动路径其中的参数noexecute为execute)。我安装了两个虚拟机,一个安装学生端一个安装教师端,为了能够互相通信,使用了桥接网络的方式。
载入OD
这种软件,向来无壳,所以,直接拿来就分析。看一眼入口点,VC6特征如此明显,而加载的模块列表中也有MFC运行库,所以,明显的,MFC编写的程序。(如图) 就算再不确定,查找一下所有模块间的调用,一眼看出…… 寻找可操控点
这里,我直接去看了看教师端,发现设置里面有两个比较有趣的选项:(如图)
这样,补丁的地方就显而易见了,它既然有这个选项,那么就说明,学生端在执行这条命令的时候,一定会有一个判断,对教师机是否选中这个选项的判断,所以,有了以下两种思路: 1.截获封包,自己处理其中的数据后再让学生端处理 2.直接修改学生端对应的反汇编代码,实现暴力**修改 由于本人才疏学浅,无法胜任第一项工作,只好去实现第二种思路,况且,第一种思路编出来的程序,难道不需要一直运行着?本人没做过,的确是不知道。 开始分析
既然已经有了可以操控的地方,那么就应该开始分析。首先,要知道从何下端,在何修改。那么,在何处下端可以找到关键点?我认为消息循环处理处是一个不错的选择。寻找消息循环处理的代码有很多种方法,在此我只说适用于此软件的一种方法,那就是在置顶窗口的函数处下断。
如何知道它使用了哪个置顶窗口的API?必须了解的是,这个软件窗口是本来不在前台的,要被设置到前台去,所以只能使用SetForegroundWindow,因此下断SetForegroundWindow,而后开始在教师端开始控制……
果然断了下来,不过断下来的地方正和我意,居然是消息循环处理的地方……既然如此,那么开始劳动……单步走,看看要到哪个CALL里面去。(如图)
跟了几步就到了,由于虚拟机没有安装中文输入法,英语水平也很差,于是乎使用了拼音,各位大神不要见怪。跟入CALL,通过不同设置的对比,得到两个关键跳转的地方。 004149EA75 04 jnzshort StudentE.004149F0 00414AC80F85 85000000 jnz StudentE.00414B53 这两个跳转如果全部NOP掉,那么就会变成窗口。那么,鼠标键盘锁在什么地方?继续向下走。(如图)
得来全不费功夫,感谢作者,你起名起的太诗情画意了,完美!不过,这难道不是一个良好的编程习惯么?跟入,处理,将实现代码前的跳转全部处理掉,作出记录,然后,屏幕广播到此收工! 再在教师机处通过使用的功能,将其他的CALL的功能也摸清,结果如图。 感觉整个人生都美妙了许多,不禁飘然若仙~~~ 编程处理
如果是那些大牛们,自然是使用WIN32API啊、汇编啊、什么什么什么,然而,我等小菜,也就只能使用MFC来写了,因为……感觉…界面实在难做…本意又不是来做界面的…至于易语言~感觉用起来太难受,想了想还是算了… 于是乎,开始了无聊的编程~那么,关于编程我就不多做说明了,反正是一个内存补丁,没有多少技术含量。由于以前分析极域电子教室2.0的时候发现它HOOK了OpenProcess这个API,所以……直接去调用Ntdll.dll里面的ZwOpenProcsss了……貌似4.0版本没有HOOK它……两个需要用到的结构体定义如下:
[C++] 纯文本查看 复制代码 typedef struct _CLIENT_ID
{
HANDLE UniqueProcess;
HANDLE UniqueThread;
}CLIENT_ID, *PCLIENT_ID;
typedef struct _OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
PVOID ObjectName;
ULONG Attritubes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
}OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
接着,定义这个函数参数 [C++] 纯文本查看 复制代码 #define OUT
#define IN
typedef DWORD(__stdcall *ZWOPENPROCESS)(
OUT PHANDLE ProcessHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObejectAttributes,
IN PCLIENT_ID PClient_Id
);
再后来,在程序中的调用如下: [C++] 纯文本查看 复制代码 bool MyOpenProcess(OUT PHANDLE ProcessHandle)
{
HMODULE hModule = ::GetModuleHandle(L"ntdll.dll");
if (hModule == NULL)
return FALSE;
ZWOPENPROCESS ZwOpenProcess = (ZWOPENPROCESS)GetProcAddress(hModule, "ZwOpenProcess");
if (ZwOpenProcess == NULL)
return FALSE;
CLIENT_ID ClientID;
ClientID.UniqueProcess = (HANDLE)PID; //UniqueProcess可以接受PID
ClientID.UniqueThread = 0;
OBJECT_ATTRIBUTES oa;
oa.Length = sizeof(oa);
oa.RootDirectory = 0;
oa.ObjectName = 0;
oa.Attritubes = 0;
oa.SecurityDescriptor = 0;
oa.SecurityQualityOfService = 0;
NTSTATUS status = ZwOpenProcess(ProcessHandle, PROCESS_ALL_ACCESS, &oa, &ClientID);
if (status == STATUS_INVALID_PARAMETER)
{
::MessageBox(0, L"参数错误!请检查PID!", L"警告:",0);
return FALSE;
}
return TRUE;
}
因为要获取PID,而枚举又太麻烦,于是做个编辑框让用户自己输入PID好了……还有一个需要注意的地方就是在写入补丁的时候,字节码反过来写…… 例如: int Data1 = 0x73EB;
后记
就是这么多了,我这样的小菜有错误在所难免,请各位大神指正… 补丁在WindowsXP上测试通过,在此我写死了地址,有ASLR的童鞋请自行处理…
2017.4.23 以下链接失效,各位很抱歉,由于我也没有备份,所以无法补链
另外,我已将补丁开源,地址:https://yunpan.cn/cvZIyTVefngH8 访问密码 11fa 成品链接:https://yunpan.cn/cvZIJaDNPZgUg 访问密码 c833 极域4.0安装包链接:https://yunpan.cn/cvZIYdqXJ4kXs 访问密码 c01c 祝各位国庆愉快~
|