【转】android call(mo)流程介绍,【转】超详细找call写call教程
神话:作为一名新手,在阅读这篇文章并结合自身的学习经验后,深感裨益。期待能为一些读者提供参考价值。
我们需要明确一点:在进行某些特定的操作时(比如在游戏智能辅助器中模拟键盘操作),被操作的对象始终是当前窗口。当窗口发生切换时(如从一个界面切换到另一个界面),你的智能辅助器将失去作用。而 CAL 命令则解决了这一问题。此外还有一个问题暂时我不感兴趣去深入研究它目前专注于研究 CAL 命令(萝卜加上)
下面我会详细解释这个教程的内容安排。为了更好地教学目的,在课程设计中选择了一个具体的实例——一个find CALL的练习程序作为教学案例。选择不使用游戏作为教学案例是基于以下原因:由于长时间寻找呼叫在游戏环境中较为耗时,并且不利于作为简明扼要的教学案例进行讲解。此外,在本次课程中还涵盖了相关参数设置的相关知识介绍以及应用方法的具体阐述。
wygailf
wygailf
[图]
这个就是我们用到的程序,OK,打开他并且用OD附加进程!
[图]
并使其进入“运行”状态
很好,在目前阶段没有启动CALL程序,请容许我来解释一下。让我们先了解一下 CTRL+F9 这个功能键的作用——它是‘运行到返回’的意思。那么为什么要按下这个按钮呢?——就我的理解而言,在编程中我们可以将程序比作一个层级分明的系统结构图:每一层都像是一个封闭的小盒子;而 CALL 则是我们想要从中获取所需元素的方式。这样一层层打开就像从盒子里提取物品一样方便快捷。
那么,在想获取CALL操作时该怎么办呢?当然是启动并获取一次Boxes操作,在此期间需要反复启动Boxes并从其内部获取内容.....而这个Ctrl + F9正是实现从Boxes中获取内容的操作流程结束时的一个关键步骤。
而这个RET正是突破当前层级的关键因素之一。每一个RET都可能是这一层次的基础元素。从而也解释了为什么有时候按下三下或四下的Ctrl + F9的原因
好,说的就这些。下面LET'S GO!
我们首先下断点bp send。
[图]
接着按下回车键。如果不确定自己是否成功设置好了断点,则可以在软件界面OD中按ALT+B来检查状态。
[图]
请在这里写下我们的停用标记位置并将其设置为有效状态。无论何时都是有效的,并且同样可以选择暂停它(即关闭其有效性)。在任意一个停用标记处按下回车键即可将其切换为"禁用"状态(即暂时关闭其有效性)。这样操作后就完成了这一设置步骤。此处无需进一步说明,请继续开始操作。
==============================================================================================================
首先,我们来个HP药水试试!
[图]
在这里选择吃药。然后OD会断下!
[图]
这里是程序断下的地方,我们可以看到下方有如下注释:
[图]
SEND来自.....说明这里是send函数被断开的地方。
继续,CTRL+F9我每一步都会记录下来,一点一点给新手解释为什么!
[图]
当我按下Ctrl+F9并切换一次后(即第一次切换),当前页面显示的是一个标记标记符标记标记符(即标记符)。另外补充说明一下:看看当前页面上的标记符值是否为10?在这里标记符值是10表示该操作包含4个参数(即每个参数占用4字节的空间)。不过按照这个逻辑计算的话(即考虑每个参数占用空间大小),结果应该是 标记符值等于十六才对啊(即标记符值=16)。不过这与实际情况不符
这里的十进制数值为十六进制中的十位数字(即A)。因此有:十六等于二乘以四平方(即十六=2×4²),所以此处执行RET操作(RET 10)。以下开始讨论:观察到调用标记(CALL)出现吗?当我们发现调用标记时,请立即执行以下操作:按下Ctrl+F9键(无需犹豫地执行此操作),这表明我们仍处于系统的正常运行范围内。尚未进入应用程序的核心部分。为什么Windows系统与应用程序不同?因为应用程序必须依赖于Windows平台才能运行起来。一旦应用程序需要执行特定任务,则必须向Windows系统发出指令(通常使用SEND函数)。具体来说,请将应用程序请求的操作发送给Windows系统:表示应用程序准备进行某项操作;Windows确认其权限;应用程序指示具体执行的位置;Windows返回确认信号——这就是所谓的调用标记(CALL)。在这里我们已经成功捕获到了所需的调用点。
[图]
第二次CTRL+F9,这里的CALL还是差不多,还在系统层内。我们继续!
[图]
OK,以上是第三次按CTRL+F9所看到的信息。
已经抵达了程序层面。也就是这个点很可能就是我们要找的那个关键点。那么接下来我们就来进行测试吧
好的,我们来看这一段
[图]
lewei2000提醒:以下几点解释有误,初学者略过,楼主还需深化汇编知识
查看第一行:mov double word ptr fs:[eax] and [edx] -------这里的含义是:将指针赋值到双字,并且fs块中的[eax]和[edx]表示将[edx]中的值复制到[eax]中以实现两者相等(经版主提醒需做澄清此理解属于个人见解而非正规的技术解释)
将数值压入栈;实际上与mov指令的功能相似;因此,在这种情况下 push 到哪里了呢?由于在第一条指令中已经使用了EAx寄存器;那么在这里应该使用EBX寄存器;也就是,在这种情况下操作的结果会被存储在EBX寄存器中。
查看第三行:lea eax,pword ptr ss:[edp-4]。该指令的作用是将运算结果存储至eax寄存器。既然如此,请问您是否已经理解?具体的结果我们稍后再分析。
看第四行:CALL不解释。就是我们需要的东西。(但其实不是)
看第五行:ret 返回的意思。
我们可以认为,在这种情况下(即这段代码是我们需要处理的情况),我们应该如何编写这段代码?又该如何将其整合到整个程序设计中?
为了制造悬念,在我已经进行了相关测试的情况下(因为之前已经验证过),这里并不是我们需要的 CALL ,我不打算详细说明。一旦找到合适的 CALL ,我会详细介绍如何编写它。
好继续CTRL+F9下图
[图]
看这里,跟上面一样,这个返回没用,我们继续CTRL+F9。
[图]
现在这里又出现了某个CALL。那我们考虑一下是否是这个吧?如何调用这个CALL呢?
首先,请问这个是否是一个带有参数的调用?那么如何进行测试呢?---不妨试试看但是这里的调用带有参数。接下来我们将继续深入分析。
我们如何确定该CALL传递了哪些参数?让我们想想看:该CALL所使用的参数通常会显示在何处?查看结果通常出现在哪里?比如,在哪个位置或区域可以看到这些信息?--断点~!(周杰伦唱的)
好,在上面CALL那里下断点~选择CALL,按F2
[图]
此处前段显示为红色。一旦断点正常运行,则无需再对前端进行处理,在ALT+B菜单中取消选中SEND操作(按Delete键取消选择)。
OK,我们让程序恢复到运行状态!
[图]
好,我们看到,测试程序中显示,使用了一个补血药品。OK,我们继续按“吃血”!
[图]
请确认是否已经定位到错误位置?我们的下界线设置在此处。无论该CALL是否有效,请确保在执行吃血过程时调用此CALL。
上一阶段我们讨论了关于CALL函数的相关知识时提到过一些相关细节。其中调用该函数时所需的运行环境即为该函数所需的一些参数。具体来说,在哪些情况下这些参数会对程序的执行结果产生重要影响呢?例如,在执行该过程时会消耗蓝值;而如果是在某些特定情况下则会消耗蓝值。
现在我们在使用程序中调用了寄存器。查看寄存器的状态信息时发现有两个显示为红色标记的位置。这表明,在进行一次CALL操作时,在这两个位置上被系统自动分配了地址索引。因此,在此次操作中所使用的两个地址就是用于实现该CALL指令的。
处于运行状态。这表明,在执行该CALL指令时,只要寄存器EAX中的值为00D51FE4且寄存器ECX中的值为0042ABE4即可启动程序。除此之外。
情况,这里我先卖个关子。
这里也解释了上面的那个不是我们用到的那个CALL如何看参数!
好,这里我们写一个小程序来调用CALL。
===========================================================================================
好,不管是不是这个CALL,我们先来测试一下
我是用Delphi进行开发的,在这里我想补充一点。其实语言仅是一个工具,在真正关键在于掌握了其中的道理之后就不在乎具体使用的语言细节了。其实在我们当前的学习阶段,两者的区别无非在于指令的不同而已。
我会把如何写的理论告诉给大家。让大家知道------花儿为什么这样红!o(∩_∩)o...哈哈
首先, 我们要invoke一个程序的CALL, 做什么事情呢. 自然是指定这个程序啊! 该如何做呢? 如果这里您不清楚, 请指导您前往句柄处深入学习.
Hwnd := FindWindow('1', '2')======其中Hwnd是一个变量代表窗口句柄。FindWindow是一个用于查找窗口句柄的命令,在此有两个参数被替换为'1'和'2'。其中'1'在命令中应代表窗口类名。
2在这里应该是窗口标题。
调用该函数时传入的两个参数分别是窗口句柄和赋值变量;这个函数属于一类执行特定操作的指令;用于获取指定窗口及其相关线程信息的指令;有两个输入字段;其中第一个参数对应于窗口的主句柄;第二个参数用于接收计算所得的结果;其返回的结果可以直接用于后续处理步骤
可以把窗体线程的进程ID赋值给某个变量。具体实现方法是:通过以下方式实现:调用GetWindowThreadProcessID函数,并将其第一个参数设为Hwnd窗口句柄、第二个参数设为@ThreadID。
该指令用于打开进程并返回其进程ID。该指令包含三个参数:分别是参数类型、句柄继承符以及线程ID。其表示方式可写作Pid:=OpenProcess(Process_all_access,false,ThreadID)
Process_all_access即表示打开进程的方式,在此仅需采用全部格式即可。无需深入理解其机制,在此只需求会编写代码即可。
这里写好了,我们可以检测一下是否成功。
[图]
[图]
这里就是找线程ID了!下面写注入
过程注入函数
function TForm1.InsterGameFun(Hid:cardinal;FunName:pointer):cardinal;
var
{要注入线程的窗口句柄和临时存放的句柄}
TmpHandle: THandle;
ThreadID: Thandle;
ThreadAdd:pointer;
WriteCount: DWORD;
begin
ThreadAdd := VirtualAllocEx(Hid, nil, 128, MEM_COMMIT, PAGE_EXECUTE_READWRITE);//在目标进程建立内存空间
WriteProcessMemory(Hid, ThreadAdd,FunName, 128, WriteCount);//将在内存区域中注入该过程.
TmpHandle := CreateRemoteThread(Hid, nil, 0, ThreadAdd, nil, CREATE_SUSPENDED, ThreadID); // 为注入后进程获取句柄ID
result:=TmpHandle;//返回句柄ID
end;
这里照抄也可以,反正就是这么写的,每步怎么个意思我也标示了。
注入也写了,窗口也获取了,剩下的就是写CALL了。
好的!我们看这个图片
记得我刚才说的EAX(00D51FE4)和ECX(0042ABE4)了吗?
按照这里来说。只要我们写命令
pushed
asm
mov eax,$005D1FE4
mov ecx,$0042ABE4
call $00452E98
popad
一般这样的命令就可以了。
然而这种写法在实施过程中未能产生预期效果。这可能源于何处的失误?我们需要对比两幅图
我们对比两个图的寄存器中的值。
经观察,在EDX系统中返回后的数值并未发生变动。这表明EDX可能受环境因素影响。另一方面,在ECX系统中数值显示前后不一,请问这是由于环境因素导致吗?
我们做如下测试。
procedure HP; //吃红
var
Address:pointer;
begin
Address:=pointer($00452e98);
asm
pushad
mov eax,$00D51FE4
mov ecx,$0042ABE4
mov edx,$00453028
call Address
popad
end;
end;
我们这么写,测试一下,成功!那么去掉ECX呢?也成功!
这里就是EDX和EAX是真正的参数了。
========================================================================
好的,我这已经讲解的超级详细了,如果还有人不明白,那我真吐血了!
进而可以写出蓝哼回城的CALL呢?如果无法写出的话,请问还需要重新审视这篇文章吗?
我们这里有没有交流群,我QQ:543820650,可以拉我进去吗
