赞
踩
具体的描述大家可以在网上找,在这里我就不再罗嗦了,大致意思为:通过调用程序自身的一些函数达到某种目的。
虽然前面的HOOK已经可以实现一些特殊功能,但是对于一个线上的软件,只在本地做了修改是没有用的,因为服务器的数据并没有改掉,因此出现了CALL。
仍以前面的Game为例进行CALL的说明,如下“弄死我自己”。
1、CALL代码构建
根据已有的逆向分析结果,该游戏中角色类中有一个成员方法——被攻击的函数beAct,其有两个int类型参数,分别为:伤害damage和攻击者在数组中的下标index。
首先还是需要在Game中分配一块内存空间写入CALL代码,如下:
// 还是瞎写的哈 。 #define PTR_THIS 0xaaaaaaaa #define ACT_CALL 0xbbbbbbbb char call_data[] { 0x51, // push ecx 因为后面使用了两个寄存器,要先将原来的值保存起来 0x50, // push eax 0x6A,0x02, // push 攻击者在数组中的索引 0x68,0x00,0x00,0x00,0x00, // push 伤害,4字节,后面用指针打进来 0xB9,0x00,0x00,0x00,0x00, // mov ecx, 被攻击者的指针,即保存this指针 0xB8,0x00,0x00,0x00,0x00, // mov eax, 被攻击函数的地址,使用寄存器是为了不计算 0xFF,0xD0, // call eax 调用被攻击函数 0x58, // pop eax 恢复这两个寄存器的值 0x59, // pop ecx 0xC3 // return 函数要返回,否则崩溃 }; int* _damage = (int*)(call_data + 5); _damage[0] = 99999; int* _beActer = (int*)(call_data + 10); _beActer[0] = PTR_THIS; int* _actCall = (int*)(call_data + 15); _actCall[0] = ACT_CALL;
关于call_data的说明:
2、如何调用CALL代码
虽然代码写完了,但是怎么调用,即怎么让CPU执行到这里?
我们都知道,进程是没有执行权限的而线程是有的,所以当进程创建时都会有一个主线程进行CPU的执行,进程为线程提供了一些环境以及部分的管理工作,所以问题就变成了获得线程执行权限。
方法有两个:1)劫持线程;2)创建远程线程。
本例以创建远程线程说明,因为劫持线程有一部分是HOOK。
调用API,如下:
DWORD Tid;
CreateRemoteThread(
hGameProcess, // 目标进程句柄
NULL, // 为NULL表示获得默认的安全描述符,并且不能继承句柄
0, // 初始堆栈大小 为0表示使用默认大小
(LPTHREAD_START_ROUTINE)call_kill, // 线程执行的起始地址 (函数指针)
0, // 线程函数的参数,为0表示没有参数
0, // 创建线程后 立即执行
&Tid // 返回线程id
);
其中call_kill是你创建的线程从哪里开始执行,即CALL代码写在内存中的地址。
当在对话框内勾选“杀死我自己”时,即完成了自杀。
虽然HOOK和CALL都简单实现了一下,但是这都是靠汇编完成的,毕竟汇编是给机器看的,所以能不能不写汇编?
1、内联汇编
unsigned index = 2;
unsigned damage = 99999;
unsigned beActer = PTR_THIS;
unsigned dCall = ACT_CALL;
__asm
{
push index
push damage
mov ecx, beActer
call dCall
}
虽然还不是纯C++代码,但最起码看起来舒服多了,简明扼要的表达了我要做什么:传参、保存被攻击者的this指针、调用被攻击函数
2、纯C++代码
具体代码就不提供了,大致说下思路。
/*
* 该函数为CreateRemoteThread函数中参数函数指针可以指向的
* 根据已有的逆向分析,被攻击是一个类的成员函数,参数两个,均为int,分别为伤害和攻击者的序号
* 理想情况下,希望通过player->beAct(int damage, int index)的形式完成此功能
* 其中player为角色类的一个对象,此处代表人物角色
* 因为无法分析出完整的被攻击函数的实现内容,但是又已经知道了该函数的返回类型和参数,所以采用类的成员函数的函数指针来做
*/
剩下的大家自由发挥~
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。