一次svc简单绕过

遇到一个unity的单机游戏,这个游戏是别人改过的,想对比和原版有什么区别,使用frida去dump内存中的so,无奈frida直接被退出,但是游戏还是正常进入的,如下图:

而原版是没有验证的,

Hook pthread_create看下发现是在一个叫libmod.so之后闪退的

解压apk看下,lib\arm64-v8a\目录下并没有libmod.so

那大概率可能是从assets目录下解压自己的资源,再加载自己的so,但是我们并不需要直接去找哪个so有没有在assets目录下,因为上面hook pthread_create打印堆栈已经有给我们地址了,直接去那个目录找就行了,但其实有原包的情况下,直接对比两个apk也能看出多出了什么文件,把多出的那几个文件找出来,并用010打开就能知道是什么文件了,用010打开是为了看文件格式,有些文件为了隐藏,去掉了后缀名,有些是改了后缀名,但其实这些都没用,用010打开都能看出文件是什么格式的文件,除非有些是加密过的。

ida打开libmod.so,查看init_array段

妥妥的ollvm的特征。

随便进入一个函数,如下图,

根本没法看,我们也不准备看这些乱七八糟的代码。

其实直接硬改后面两个线程启动的地方就能绕过验证。也就是在两个线程启动的地方直接nop

但这里还有一种方法绕过验证

frida spawn启动后,frida被退出,然后游戏还能正常进入,而且mod功能也是正常的,看最后一次线程被启动的地方,进入0x1971e4函数,在分析这个函数之前,我们先理解一个正常开发的逻辑,正常一个检测或一个功能,通常都是封装成一个函数,方便查看,而且便于之后维护,基于这点,我们直接在函数中找call,也就是sub_xxxx开头的

进入0x1971e4看下,

没几个sub_xxxx,经过查看,函数内有很多处都有调用sub_188374 ,进入看下,是个syscall

好家伙,难怪hook各种系统函数都无效,而且入参是56,对应信号就是openat ,循环读取了什么文件,hook sub_19F974函数,代码如下:

var soName = "libmod.so"

function myfun()
{
	var moduleBaseAddress = Module.getBaseAddress(soName);
	console.log(soName + "_address:", moduleBaseAddress);
	var nativePointer = moduleBaseAddress.add(0x19F974);
	Interceptor.attach(nativePointer,
	{
		onEnter: function (args)
		{
			
			this.v1051= this.context.x0
			var str3 = this.context.x3.readUtf8String();
			console.log("str3:" + str3);

		},
		onLeave: function (retval)
		{
			console.log("this.v1051:",this.v1051.readUtf8String()); 

		}
	}
	);
}


function hook_dlopen()
{
	var is_can_hook = false;
	Interceptor.attach(Module.findExportByName(null, "dlopen"),
	{
		onEnter: function (args)
		{
			var pathptr = args[0];
			if (pathptr !== undefined && pathptr != null)
			{
				var path = ptr(pathptr).readCString();
				if (path.indexOf(soName) >= 0)
				{
					this.is_can_hook = true;
				}
			}
		},
		onLeave: function (retval)
		{
			if (this.is_can_hook)
			{
				myfun()
			}
		}
	}
	);

	Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
	{
		onEnter: function (args)
		{
			var pathptr = args[0];
			if (pathptr !== undefined && pathptr != null)
			{
				var path = ptr(pathptr).readCString();
				if (path.indexOf(soName) >= 0)
				{
					this.is_can_hook = true;
				}
			}
		},
		onLeave: function (retval)
		{
			if (this.is_can_hook)
			{
				myfun()
			}
		}
	}
	);
}

setImmediate(hook_dlopen);

读取了各种文件,它的最后一个参数也是先经过init_array中的函数先解密

对于openat 的描述是:函数执行成功返回文件描述符,失败返回-1.

那我们就直接在sub_188374函数中直接返回1吧,结果是可以,并正常运行,

其实直接对syscall直接返回1是不严谨的,因为有些情况下这样操作会导致别的问题出现,只是这游戏刚好这么操作没有出现别的问题。

frida也能正常附加并dump

之后就可以愉快的使用dump的so和原版的so进行比较

总结:

文章写的很乱,没什么技术含量,有些防护做了一些花里胡哨的操作,有时候也不用硬杠,但前提是知道hook哪些关键函数,知道一些函数的作用

欢迎加入QQ群:812701781,542863693,欢迎分享一些骚操作(备注看的什么文章)

微信公众号:MoneyHoneyCome

  • 11
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值