逆向(二):CALL

一、概念

具体的描述大家可以在网上找,在这里我就不再罗嗦了,大致意思为:通过调用程序自身的一些函数达到某种目的。

二、背景

虽然前面的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的说明:

  1. 开始的两次压栈,是因为后面需要用到这两个寄存器,所以需要先将其值保存起来,而后对应结尾的两次出栈。其中ecx保存被攻击者的指针是根据这是一个类确定的,因为ecx大多数都是保存this;而使用eax保存被攻击函数即beAct的地址是因为可以省去跳转的计算
  2. 结尾的0xC3,是为了返回用的,首先函数都有返回(虽然我们有时可以不写),其次这是分配出的一块内存空间,我们只是在这里写下了功能代码,当这些代码执行完之后,如果没有返回,CPU则会继续执行后面地址的其他指令,而后面是什么是不确定的!!!

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为角色类的一个对象,此处代表人物角色 
	* 因为无法分析出完整的被攻击函数的实现内容,但是又已经知道了该函数的返回类型和参数,所以采用类的成员函数的函数指针来做 
*/

剩下的大家自由发挥~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
x64进程远程hook,x64_远程调用函数,源码更新V1.8.2:2021/4/12 源码为下方连接帖子后续更新内容: 浅谈64位进程远程hook技术: https://bbs.125.la/forum.php?mod=viewthreadtid=14666356extra= 不管您是转载还是使用请保留版权,源码在精益论坛免费发布本人未获利,请不要用于非法途径。 --------------------------------------------------------------- 2021/4/12 模块源码 v1.8.2更新 1:修复 x64_远调用函数()在 易语言 线程调用时造成消息无法回调,导致易语言线程窗口卡死的问题。      感谢楼下易友发现的BUG,已经第一时间更新 2021/4/12 模块源码 v1.8.1更新 1:修复 hook全部卸载时的流程写法的一个错误,由于句柄的提前关闭导致多个hook点卸载不干净的问题 2:改写了消息回调时线程传参的代码优化,优化了其他一些小问题 3:  鉴于很多朋友需要,改写了模块自带实列,对TCP,UDP的两组封包函数做了hook实列写法 4:列子中同样增加对x64_远调用函数()的应用写了几个列子,如使用套接字取得本地或远端IP端口API调用的的应用实列 5:本hook模块不支持非模块内存区hook,如申请的动态分配页等,不是不能支持,只是觉得没有任何意义,对这方面有需求的,自行改写模块源码使用 提醒:hook回调函数中尽量减少耗时代码,时间越长返回越慢,回调中谨慎操作控件,如必须要用到可参考源码中实列写法采用线程操作 历史更新 --------------------------------------------------------------- 2021/3/1   模块源码v1.6更新: 1:修复  x64_远程调用函数()命令,在没有提供 寄存器 参数时,没有返回值的BUG。 --------------------------------------------------------------- 2021/2/28 模块源码v1.5更新: 一:修复win7 64位系统下枚举模块 出现部分模块长度出现负数的问题,从而导致部分win7用户不能使用 :强化 远程hook64指令_安装 的稳定性:        1,穿插代码中增加对标志位的保护,避免hook位置长度下一条指令为跳转时产生跳转错乱的问题,强化了hook任意位置的定位        2,因为穿插代码中会调用API函数,而64位汇编必须遵守栈指针16字节对齐,故对穿插代码进行栈指针16字节对齐,增强稳定性        3,hook指令安装支持长度由6-127字节 变动 为 6-119字节,原因么没必要说了,代码优化造成的,稍微少了一点无所谓了        4,对模块回调进行了适当优化处理,增强稳定性 三:应支持的朋友需要故增加 x64_远程调用函数()命令,易语言可以直接远call64进程,且无需写汇编代码或机器码指令,支持15个参数,支持返回值,支持16个通用寄存器全部取得返回值       该功能调用即16字节栈对齐,不要用户管堆栈,代码内部构成,远线程执行,你只需要知道call有几个参数,需要什么寄存器,对应提供即可。 四:有朋友说原模块x64英文看了烦,那好吧就给改成了中文标识,弄得我自己也不习惯 五:源码内列子改了改,可以自己看,需要注意的是模块注释的很详细,使用前最好看一看,尤其是hook回调接口的写法和安装的写法最好按照模块列子中的写法来,除非你能把64hook模块组看懂一遍,对于一些对本模块一知半解的朋友请不要乱改乱发,这个模块我会继续增强的,只是工作原因时间有限,只能一点一点来
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值