首页
社区
课程
招聘
[求助]如何在反汇编中手工调用MessageboxA函数?
发表于: 2007-8-7 14:28 8139

[求助]如何在反汇编中手工调用MessageboxA函数?

2007-8-7 14:28
8139
如何在反汇编中手工调用MessageboxA函数?

各位朋友,本人最近在帮助单位破解一个考试系统的时候,遇到了一个难题。不知哪位高手能帮我解决一下,不胜感谢!


这是一个网络版的考试系统,试卷和答案都是加密并且随即从服务器抽取的,交卷后不能用同一个用户再次登陆,不显示分数。经过本人的初步破解(其实是用ollydbg对反汇编代码进行一些修改),让考试系统的客户端可以用同一个人的身份反复登陆,但是如果成绩不显示出来的话,我也不知道当前这一题是否做对了。经过本人分析,发现一点交卷,程序立即运行到下图红色的部分,此时寄存器EAX就是当前的分数! 我想在这之后人工加入一个MessageboxA来将eax的值显示出来,我研究了一些汇编方面的书籍,发现messageboxa这个函数有4个参数,都是通过堆栈传递的,我就用如下代码来修改途中断点之后的几行代码:

PUSH 0
push eax
push eax
push 0
call messageboxa

我用ollydbg载入修改后的程序,当运行到调用messageboxa之后,进入了系统user32模块,没有正确显示一个对话框,而是在user32中出错了,出现了异常,我用shift+F9跳过异常,程序继续执行,还是没有显示我希望的那个显示分数的对话框,

恳请高手能够给与帮助! 小弟QQ:9034281 未命名.JPG (106.07 KB)
2007-8-5 16:02

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 0
支持
分享
最新回复 (10)
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
如果无法浏览图片请点击文中图片链接查看
2007-8-7 14:30
0
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
3
手动添加一个函数,用lord PE可以做到,我的贴子有讲到
http://bbs.pediy.com/showthread.php?t=48992
举一反三吧
2007-8-7 14:33
0
雪    币: 44229
活跃值: (19955)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
4
注意不要破坏原来的一些环境,包括堆栈和寄存器。
稳妥的做法:
pushad
……你的代码
popad
2007-8-7 19:35
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
PUSH 0
push eax
push eax
push 0
call messageboxa

eax是分数而不是分数字串的地址,无效的地址自然会出错。

这样的代码确实有问题
直接在原位置更改,出错是正常的,应该找个空白代码位置进行修改。

还有,eax中的值是不能直接使用,需要经过下面的格式化代码才可以。
可以在下面格式化之后再修改代码

call messageboxa
这样写有问题,只能在当前系统有效,应该调用的地址是程序在输入表中定义的位置
2007-8-7 22:44
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
感谢楼上诸位老师的指教!我阅读了大菜一号的帖子,并且下载研究了那个始终固顶的记事本,按照所述的方法自己实践了一下,还是不成功,我就奇怪了,为什么ollydbg反汇编代码中有如下字符串:
CALL <JMP.&USER32.MessageBoxA>   (其中,<JMP.&USER32.MessageBoxA> 是变成黄色高亮显示的,可能由于od设置不同,在别人调试的时候会显示不同颜色。)

而我却不能手工添加这个字符串到代码中去,提示:

未认可操作数!

而我手工添加: CALL USER32.MessageBoxA 是可以的,我还没有在这个论坛提问前就是这样添加的,可这样添加就会在user32.dll中出错了!

而且这次我也按照大菜一号的方法用一个jmp跳转到全0位置去建立自己的代码,而且把jmp所覆盖的原来的一行指令在自己建立的代码中作了恢复工作(只不过是调用MessageboxA以后并且popad以后才恢复的),并且注意按照看雪老师的提示,用pushad和popad保护环境。
这样仍然不行,目前我的办法仍然是用keymaker编写个注册机在那个位置把分数读取出来,但是这样超级繁琐,因为注册机只能运行一次,我每做一个选项就得退出用注册机重新登陆一次考试系统。

我的qq:9034281,希望能得到帮助!

我最新制造出来的代码是:

在0040B8A9  |.  A3 F0A95500   MOV DWORD PTR DS:[55A9F0],EAX   这个位置,eax寄

存器里就已经有分数了, 我在这一行修改成:

jmp “某个全0位置”

然后实现我的代码:

PUSHAD
NOP
PUSH 0
PUSH EAX
PUSH EAX
PUSH 0
NOP
CALL USER32.MessageboxA    '只能写成这样ollydbg才认,和od反汇编出来的调用messageboxa函数的形式明显不一样,一直不懂这是为什么!

popad  '恢复环境

MOV DWORD PTR DS:[55A9F0],EAX   还原那一行被jmp修改掉的指令
jmp  0040B8AE   跳跃回去继续执行。

可是执行到user32中就出现了异常。
2007-8-16 07:30
0
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
7
不能这样子去调用,
你看了我的贴子,应该知道我所说的函数的rva,
假设知道所添加的函数的rva的12345,映像基址为400000,
那么就应该这样调用:
push  xx
....
call dword ptr [4012345]

这样`OD会自动识别[4012345]地址的内容并转换为相应的函数字符串直观的显示出来!
2007-8-16 10:07
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
感谢大菜一号!  

因为在这个程序中,已经有3个地方调用了MessageboxA函数,所以就不需要像你修改notepad那样手工去添加这个函数了。

但是我对rva还是不懂。

大菜一号老师,能否加入qq详谈?

我的qq: 9034281
2007-8-16 10:11
0
雪    币: 424
活跃值: (10)
能力值: ( LV9,RANK:850 )
在线值:
发帖
回帖
粉丝
9
不用去添加了那就方便
OD载入,ctrl+n,找到MessageBox
在上面Enter
可以发现函数参考,随便找一个双击,来到cpu调试窗口
在调用MessageBox函数的语句上双击,就可以看到调用时所用的代码了,复制下来,就可以直接用了
2007-8-16 10:26
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
push 0
push eax  对话框的标题
push eax  对话框显示的信息,就和标题一样即可。
push 0
CALL <JMP.&USER32.MessageBoxA>  调用对话框函数显示分数。

实践证明这样写是不行的, 因为MessageboxA函数的4个参数中,第二个和第三个分别是对话框的标题和对话框的内容, 但我现在才知道那不是寄存器的值,是寄存器指向的某个内存位置或可执行程序在内存的镜像中的某个位置,因为当eax的值是1的时候(也就是分数是1的时候)在调用messageboxA函数的时候,ollydbg提示不能读取00000001之类的异常信息。显然messageboxA没有把00000001直接当成参数,而是去读取00000001指向的某个位置了。

看来距离我把分数正确的显示出来,只有一步之遥,那就是先把eax的值(也就是分数)写入内存中某个位置(或当前可执行程序在内存中镜像的某个不用的位置),然后得到这个位置的地址,将该地址负值给某个寄存器 如edx,在调用messageboxA的时候,将edx作为两个必要的参数用push压入堆栈。

但是我不知道如何将一个寄存器的值写入内存中某个位置,并且在用完以后将这个位置清除还原,可能还要调用另一个具备写入内存功能的api来实现这一点,但愿我要调用的这个api在程序中也被调用过。

继续研究中,再次感谢各位老师!
2007-8-16 23:35
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
搞了半天原来 MessageBoxA 函数中,中间那2个重要参数是内存的指针。
显然内存中只能存放0和1,MessageBoxA 会把该指针指向的内存位置存放的数字转换成ascII码显示出来。

看来要想把寄存器的值显示出来还不是那么简单的,分数是10进制,而eax中肯定是16进制,需要先把eax转换成10进制,判断是否大于10,大于则将个位和十位分开分别存放在内存中,而且还要加30,因为数字2的ascii码刚好是32,以此类推,然后将这两个内存位置的地址作为参数传递给MessageBoxA函数。  好在MessageBoxA函数的参数中刚好有两个重要参数可以分别存放个位和十位。

我学习汇编还是在当初过三级pc技术的时候,现在早就忘光了,特别是本次改造中下一步可能还要用到许多条件跳转(判断是否大于10,转换进制等),看来还有很多工作要做,不知道我这样的思路是不是太幼稚了,有没有更快捷一点的办法可以把寄存器的值直接转换成对应的ascii字符?(我说的是比如数字95直接转换成ascii字符串“95”)或者直接转换以后存储在内存中的某个地址处,我直接将此地址传递给MessageBoxA,我感觉我是实实在在的在PEDIY,呵呵。关注看雪论坛已经有5年了。当初就在研究PEDIY这几个字母到底是什么意思,后来才看出来呵呵!
2007-8-17 07:14
0
游客
登录 | 注册 方可回帖
返回
//