171114 逆向-以CM为例学习MFC机制

1625-5 王子昂 总结《2017年11月14日》 【连续第410天总结】
A. 谜之CrackMe
B.
来源就不说啦,总之是个MFC程序,运行界面如下
这里写图片描述
可以看到没有确认按钮,一般来说是由定时器消息或Text内容改变消息触发Check函数

确认无壳后拖入IDA查找字符串,轻松定位到sub_401CD0
这里写图片描述
但是向上查找交叉引用却发现落入一个偏移中,无从下手了
对其下断,进行动态调试也没有触发断点

说明这个函数被调用是有条件的

于是转换思路,选择GetWindowText这个API进行下断,果然断到:
这里写图片描述
向上查看交叉引用,发现有很多次

于是在OD中关注GetWindowTextA的取回输入的验证码时的调用堆栈,锁定sub_401ad0
这里写图片描述

刚开始没反应过来v9+96和v9[24]是什么东西,没头没尾的……
后来下断、观察汇编才发现是同一个值
被IDA反编译给坑了:v9的类型是Dword,4字节,于是v9[24] = *(v9 + 24*size) =*(v9 + 96)

也就是说
*(v9+96)称为flag
flag的初值为0(2+1%3)
于是Get两个Text并比较长度

当输入值为5时,对0、2、4作差(-0-1)
后跳入Label_15,将flag改为1
然后对1、3作差(-1-1)
再跳入Label_15,将flag改为2

于是进入校验部分,strcmp两个Text
也就是说要求input作差后==admin(所以注册码为bfnko)
成功后调用sub_4d7d49,其中有一个SendMessage,发送了0x401消息(自定义)来触发校验函数

至此,大概流程就结束了

不过当然不会这么简单啦
除了正向断GetWindowText的API,跟踪输入流找到校验的方法以外,还可以通过逆向回溯消息发送的方法来找到成功的条件

之前对sub_401CD0函数的跟踪到表就断了,这次好好研究了一下MFC的机制,再战结构体

大概能猜测它是一个类似虚表的东西,由一个指针指向函数指针数组的开头,然后通过偏移来调用
那么问题就是找到是什么消息触发了它,这个偏移机制是怎么来的
查询了一番发现这里的讲解比较详细:http://blog.csdn.net/SilverMagic/article/details/40621107
简单来说有一个消息映射表,其中有一个指针指向消息映射结构体数组,每个结构体中保存了消息值、控件ID和响应函数的地址

我们之前跟踪到的地方就是映射结构体,通过向IDA添加结构体并标识可以令其识别:
这里写图片描述
另外还可以通过工具来直接查找:
这里写图片描述
可以看到它准确的识别出了消息0x401,指向了sub_401cd0函数
sub_401AD0的调用则是定时器TIMER引起的

知道了0x401消息,只要直接搜索立即数即可:
这里写图片描述
也能追到Timer函数中的SendMessage

C. 明日计划
RE练习

最近一直都在看ExeToc的源码,仔细看一看,问题比较的多,但是,至少整体框架有了。 这次修改主要是几点: 1、给伪代码视图上了颜色 (反编译后有三个视图,反汇编视图、反编译视图与伪代码视图),快捷键分别是 a、d、i 代码: void CRorEditView::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) { CRorTextView::OnChar(nChar, nRepCnt, nFlags); if (nChar == 'i' || nChar == 'I') // 显示伪代码信息 { this->ResetView(); this->DeleteAll(); this->LocateTextBuffer()->m_xml.Clear(); g_EXE2C->Hxd_prtout_Pcode(&this;->m_pTextBuffer->m_xml); this->Invalidate(); return; } if (nChar == 'a' || nChar == 'A') // 显示汇编信息 { this->ResetView(); this->DeleteAll(); this->LocateTextBuffer()->m_xml.Clear(); g_EXE2C->hxd_prtout_Asm(&this;->m_pTextBuffer->m_xml); this->Invalidate(); return; } if (nChar == 'd' || nChar == 'D') // 反编译的信息按CPP格式显示 { this->ResetView(); this->DeleteAll(); this->LocateTextBuffer()->m_xml.Clear(); g_EXE2C->prtout_cpp(&this;->m_pTextBuffer->m_xml); this->Invalidate(); } } 2、修改了cmp伪代码与jxx代码的合并函数(还需要完善) 3、修改了变量优化函数 (还需要完善) 4、修改了流程分析函数(还需要完善,我正在改写这部分,没写完,原先相同功能的代码也没有删除) 我感到凭我个人的精力是不能完成此程序的,有兴趣的网友可以一起写一写。 如果你在分析程序时,反汇编时显示unknown的代码,或伪代码中显示unknown的代码,或跳转while、for等循环没有分析出来,不要惊讶。这些都需要大量的精力,需要大家共同完善
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值