首页
社区
课程
招聘
[原创]第四题:西部乐园
发表于: 2019-12-9 13:53 4200

[原创]第四题:西部乐园

2019-12-9 13:53
4200

首先百度看看什么是驱动程序,看了几篇有关windows驱动开发的文章,总结一下,就是个sys文件,涉及到服务和设备,需要权限才能运行。

打开题目压缩包,一个带管理员图标的exe,一个sys文件,readme里说要开测试模式,先分别ida分析看看。
exe文件里函数不多,基本上每个我都点了一遍,有创建服务的,启动服务的,获取文件完整路径和单独的文件名的,以及调用printf和scanf的。。。最后来到主程序。
 call_printf(aEnterPassWord);
  call_scanf(aD, v5);
  if ( (signed __int64)v5[0] <= 96000 && (signed __int64)v5[0] >= 90000 )
 call_printf(aEnterPassWord);
  call_scanf(aD, v5);
  if ( (signed __int64)v5[0] <= 96000 && (signed __int64)v5[0] >= 90000 )
主程序里调用
了启动服务的函数,输出了密码提示,并且用scanf接收输入。scanf用的格式字符串很奇怪,在这里:
就是一个%d,也就是一个数字。但是显然下面这个更像是一个序列号字符串才对。
我这里甚至动态调试了几次,才确定scanf确实用的%d,接收一个90000~96000之间的数字。
作为测试,直接运行程序,输入数字,发现不在范围内的就错误弹框,范围内的程序就直接结束,因为我还没开测试模式。
我坚信密码不可能是范围这么小的五位数,并且认定后面还会调用scanf,并且使用下面这个格式化字符串,但是这样不就有两次输入了么?(后来发现真的就是五位数)
继续往下

最终调用的是DeviceIoControl,从栈上看一下传进去的参数
这里badcallbak是一个错误弹框的函数指针,codestr是从内存中复制过来的数组,在调用前,writeptr这个函数向其中+2和+18的地方分别写了两个8字节的指针,value是输入的数字。而inbuffer中第一个qword中,也就是前8字节是输出缓冲区的地址。(ida的栈方向好像是反的,直接看变量的地址发现后面几个才在高地址)
其中 sub_14000256E很奇怪,貌似是取栈顶的值赋值给参数,这里v4对结果根本没影响,所以跳过不管
.text:000000014000256E sub_14000256E   proc near               ; CODE XREF: MAin+10E↑p
.text:000000014000256E                 mov     rax, [rsp+0]
.text:0000000140002572                 mov     [rcx], rax
.text:0000000140002575                 retn
.text:0000000140002575 sub_14000256E   endp

接着分析sys文件,从driverEntry跟进去,很快找到

于是到MAjorFunc函数去看,这个函数要处理的就是DeviceIoControl

这里ida自动分析的结构体出了点问题,删掉一个值后居然直接直接给换成了另一个。不过因为知道输入缓冲区的内容,根据后面的使用情况还是可以猜出这些变量的内容。
这里被我标记为maycall的函数里面调用了KeInitializeApc,KeInsertQueueApc,虽然不知道APC是什么,但显然不能让输入值是之前参数里错误弹窗的函数,于是可以确认要满足
if ( *(_DWORD *)((char *)inbuffer + v11 + 36) == v12 )
sub_14000110D这个函数也很奇怪,按照ida的伪代码,里面直接用了未初始化的指针,本来想具体看看汇编的,但是决定先看看返回的这个数字怎么用,说不定能猜出来。
inbuffer中前32字节是四个数字,再后面就是从内存中复制出来的数组,按照后面的调用看,这里在经过decodeit之后直接把整个数组用qmemcpy复制然后作为maycall的参数,也就是说后面这个数组里存的是验证成功的回调代码,只是需要经过正确解密,而解密是否成功就通过if里取第一个dword来判断。 (may_outbuf也是猜出来的,因为v13是函数地址,被赋值为从inbuffer中传进去的outbuffer起始地址,因此memcpy这里肯定是要改变outbuffer的内容,才能作为解密后的代码。)这里var决定的传入decodeit的参数,第一个参数应该是要解密的代码的开头地址,第二个参数是要解密的数组长度,最后一个参数是输入数字。这里如果var是-4的话刚好就是整段代码全部解密,实际上我开始就假设var是-4(猜错了)。

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2019-12-9 14:11 被mb_ibocelll编辑 ,原因: 纠错
上传的附件:
收藏
免费 3
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//