首页
社区
课程
招聘
[原创]Find CALL Tool(带源码)
发表于: 2014-7-24 17:13 29115

[原创]Find CALL Tool(带源码)

2014-7-24 17:13
29115

Find CALL工具功能与Cheat Engine类似,只不过Cheat Engine是找数据,Find CALL工具是找功能调用函数。这两个工具都为外挂制作者和游戏安全人员带来福音。Cheat Engine和Find CALL工具界面如图1所示:
                                   
                                             
                                   
                                           图1 Cheat Engine和CallTool界面

在分析游戏中,游戏界面中是没有对应功能按钮的,都是绘制的,这样无法下按钮消息断点,定位功能代码不容易,有了CallTool工具就可以快速定位到功能函数。

一、工具使用:
这里使用Find CALL工具快速找记事本的“替换”功能以说明其使用。
1).在PID栏填写记事本进程ID:
                                    
                                              图2 在PID栏填写记事本进程ID

2).点击“Call按钮”,弹出成功对话框:
                                    
                                                    图3 弹出成功对话框

3).点击记事本“编辑”->“替换”,在“查找内容”对话框输入“aaaaaa”后点击“查找下一个”按钮:
                                    
                                                   图4“查找下一个”按钮

4).现在此功能已经调用了1次,更新调用次数为1次,并点击Updata按钮:
                           
                                              图5  更新调用次数为1次

5).重复步骤4,更新界面选项为2次,点击Updata按钮后仍然提示剩余4个CALL:
                              
                                              图6  更新调用次数为2次

此时说明不能再缩小范围了。

6). 点击Read按钮,右上方的List控件会显示找到的CALL,ID编号、CALL的地址、CALL的目标地址、调用CALL的数量:
                                      
                                                 图7  点击Read按钮后的显示

7).点击Clear按钮,再点击Order按钮,提示再次执行要定位的功能以便CALL Tool工具能定位:
                              
                                                 图8  点击Clear、Order按钮后

8).重复执行步骤3,再点击“Read按钮”,左上方的List控件显示找到Call的调用顺序:
                                      
                                                图9  点击Read按钮后界面显示
                                                   
9). 点击Clear按钮,再点击Stack按钮,提示再次执行要定位的功能以便CALL Tool工具能定位:
                               
                                                图10  点击Clear、Stack按钮后

10). 重复执行步骤3,再点击“Read按钮”,下方的List控件显示找到Call的堆栈调用关系:
                                      
                                                图11  点击Read按钮后界面显示

11). 图11有4条堆栈调用,从右往左依次调用,第一条(ID为0)调用路径是0x1007511->0x10029e0->0x100372e->0x1001faf。可以看出第二条路径(ID位0001)的Target为 010029e0在第一条调用路径上; 第三条路径(ID位0002)的Target为 0100372e在第一条调用路径上; 第四条路径(ID位0003)的Target为 0100372e在第一条调用路径上。
所以第一条调用的0x1001faf地址是最底层的调用Call。使用OD附加并 go到对应地址0x1001faf,发现其下有MessageBoxW调用,F9运行,断点触发:
                                                                    
                                               图12  MessageBoxW地址处断下

跟踪到MessageBoxW,可以看到OD堆栈窗口出现找不到“aaaaaa”,正是记事本弹出的提示对话框:
                                       
                                       图13  找不到“aaaaaa”弹框提示

因为替换查找功能执行后,找不到,就弹出提示对话框了。这就说明了0x1001faf的地址是最底层的Call,其它3个Call就是真正功能的执行函数了。
上文说明了如何找记事本程序的功能函数,同样可利用CallTool工具在游戏中查找某功能。

二、代码分析:
CALL TOOL工具实现的核心思想是反汇编需分析的程序,寻找Call调用(机器码0xE8、0xFF15),替换成自己的shellcode函数,shellcode函数预先在堆中分配好。shellcode函数中实现记录函数调用次数、调用先后次序、函数之间的堆栈层次关系。以下给出记录函数调用次数的流程如图14:
                          
                                              图14  记录函数调用次数的流程图

以下给出记录函数调用次数的伪代码:

bool CCallToolDlg::GetCallCountHook(PBYTE pModBaseAddr, PCHAR szExePath, HANDLE hProcess)
{
打开需分析的可执行文件…
设置文件读取游标为文件开始处…
读取文件内容到申请的内容…
    用反汇编引擎反汇编文件内容,寻找call xxx、call [xxx]调用,并记录下总共call数量;
	使用VirtualAllocEx(hProcess… 在进程内存中为每个call申请3个DWORD内存空间;
	if (申请成功)
	{
		…
		BYTE shellcode[] = 
		{
			0x60, 0x8D, 0x35, 0x24, 0x09, 0x3E, 0x00, 0x8B, 0x06, 0x40,					0x89, 0x06, 0x61, 0x68, 0x7E, 0x38, 0x00, 0x01, 0xE9, 0x30, 
			0x14, 0xC2, 0x00
		};
		while (循环读取代码段)
		{
			用反汇编引擎反汇编…
			寻找0xE8(call xxx)、0xFF 0x15(call [xxx])调用…
			获得Call xxxx中xxxx内容…					
把Call xxxx中xxxx内容由"相对地址"转换为"绝对地址"(在申请的内存中)…
加判断,防止把数据识别成代码, 
			RtlCopyMemory(CI.ShellCode, shellcode, 23);	//把shellcode copy到结构体
			*(PDWORD)(CI.ShellCode + 3) = pRemoteAddr + sizeof(DWORD) * 2; //赋值shellcode中的lea esi,dword ptr ds:[3E0924] 为目标进程dwCount位置
			*(PDWORD)(CI.ShellCode + 0x0e) = dwCodeAddr + 5; //赋值shellcode中的push 100387E 为原Call的地址下一条指令[Call(0xE8)指令占字节]
			*(PDWORD)(CI.ShellCode + 0x13) = dwTarget - (pRemoteAddr + sizeof(DWORD) * 4 + 0x12) - 5; //赋值shellcode中jmp 01001D73 计算跳转偏移(为原Call到shellcode的偏移)

		    WriteProcessMemory(hProcess, (LPVOID)pRemoteAddr, &CI, sizeof(CALL_INFO), &NumberOfBytes); //写入shellcode到申请的空间
			更改Call Target 为JMP ShellCode…
		}
	}
	关闭打开的文件…
}

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

上传的附件:
收藏
免费 4
支持
分享
打赏 + 1.00雪花
打赏次数 1 雪花 + 1.00
 
赞赏  mb_dzuuihxw   +1.00 2024/03/15 大佬findCallTool能出个64位版本吗?
最新回复 (77)
雪    币: 2105
活跃值: (424)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
沙发 思路不错
2014-7-24 17:21
0
雪    币: 7048
活跃值: (3527)
能力值: ( LV12,RANK:340 )
在线值:
发帖
回帖
粉丝
3
不错,感谢共享,可是为什么源码里会有svn的东西0.0
2014-7-24 17:40
0
雪    币: 6
活跃值: (1509)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
嗯 学习下 思路
2014-7-24 17:42
0
雪    币: 2664
活跃值: (3401)
能力值: ( LV13,RANK:1760 )
在线值:
发帖
回帖
粉丝
5
挺好,感谢分享...
2014-7-24 17:43
0
雪    币: 6556
活跃值: (4356)
能力值: ( LV10,RANK:163 )
在线值:
发帖
回帖
粉丝
6
思路不错,学习一下~
2014-7-24 17:46
0
雪    币: 1042
活跃值: (500)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
7
随手找了三个程序,输入PID点CALL,目标程序都会退出是咋回事
2014-7-24 18:37
0
雪    币: 114
活跃值: (180)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
非常不错,收藏一个~
2014-7-24 19:06
0
雪    币: 62
活跃值: (971)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
测试了一下,很好的思路,希望楼主继续开发,楼主用到了DLL注入目标进程吗。
2014-7-24 19:19
0
雪    币: 6517
活跃值: (2397)
能力值: ( LV12,RANK:320 )
在线值:
发帖
回帖
粉丝
10

wonderzdh:
测试了一下,很好的思路,希望楼主继续开发,楼主用到了DLL注入目标进程吗。

没有用到DLL注入目标进程,直接读写目标进程。
2014-7-24 19:44
0
雪    币: 116
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
和我以前发的一个帖子介绍的方法类似。不过 我的call不是自己找的,是copy的IDA分析出来的所有地址,这样有一个好处就是,ida能识别一些库函数,这样我们可以直接忽略掉;其次你是把call修改为jmp一个函数,我是直接修改为0xcc,用的异常处理来获取断点异常;
btw:其实我一直想做的一件事就是,给d3dx的所有函数下个断点,或者像楼主这样做个hook,每次执行到函数时,就统计下当前内存的使用量,最后比较看哪些函数运行后,内存变化大,看能否干掉这些函数,去做黑屏优化,呵呵,只是个思路,我自己没搞过。
2014-7-24 19:47
0
雪    币: 1136
活跃值: (683)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
虽然还没用,但是感觉很不错
2014-7-24 19:48
0
雪    币: 229
活跃值: (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
感谢分享,学习一下
2014-7-24 19:52
0
雪    币: 7
活跃值: (49)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
14
话说这工具挺实用。。
我好像看见一疑似bug。。。CallToolDlg.cpp 505行....
2014-7-24 20:12
0
雪    币: 702
活跃值: (4579)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
15
不错 楼主继续完善下~
2014-7-24 20:20
0
雪    币: 22
活跃值: (458)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
16
很好 这个做好了会很有用!
2014-7-24 20:20
0
雪    币: 69
活跃值: (157)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
17
哇塞, 这是神器啊. 要好好利用.  尽量完善,做成产品.
2014-7-24 20:46
0
雪    币: 757
活跃值: (3843)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
18
很强大,支持下!
2014-7-24 20:51
0
雪    币: 35
活跃值: (96)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
19
支持一个
2014-7-24 20:55
0
雪    币: 62
活跃值: (971)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
20
ida识别原理是啥?也是找Call的二进制代码?
2014-7-24 21:14
0
雪    币: 144
活跃值: (53)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
21
mark
2014-7-24 21:23
0
雪    币: 768
活跃值: (535)
能力值: ( LV13,RANK:460 )
在线值:
发帖
回帖
粉丝
22
神器,谢谢楼主好思路
2014-7-24 21:33
0
雪    币: 27
活跃值: (127)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
23
思路很好,实际效果需要测试
2014-7-24 21:34
0
雪    币: 116
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
24
你把程序拖到ida里面,ida会自动识别函数嘛,不是有个functions window页么,或者你按shift f3;与找call没有关系,是识别call, 你看楼主帖子,不是最开始点那个“call”,会识别程序里有200多个函数么
2014-7-24 21:36
0
雪    币: 100
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
25
思路不错,继续完善
2014-7-24 21:46
0
游客
登录 | 注册 方可回帖
返回
//