一个Unity项目,没有办法得到一个C++类方法的调用时机,怎么可以手动的调用这个方法
public class A {
public byte[] afunc() { }. // 需要调用的方法
}
byte[] B(A tex) /// 可以hook 的方法
现在的情况是,可以hook到一个B 方法,B 方法参数是一个A对象,能否在这个方法里面调用A的 afunc, 并拿到返回的 byte[] 结果。
B 方法的A,暂时只能是一个void* 指针,
一个Unity项目,没有办法得到一个C++类方法的调用时机,怎么可以手动的调用这个方法
public class A {
public byte[] afunc() { }. // 需要调用的方法
}
byte[] B(A tex) /// 可以hook 的方法
现在的情况是,可以hook到一个B 方法,B 方法参数是一个A对象,能否在这个方法里面调用A的 afunc, 并拿到返回的 byte[] 结果。
B 方法的A,暂时只能是一个void* 指针,
假如用 汇编代码直接跳转到需要调用的方法,寄存器和 栈应该怎么构造?
给你举个例子:
Unity 里的一个 cs 类
public class Profile
{
public void set_Coins(int value) { }
}
通过il2cpp 编译后的cpp方法签名。第一个参数和最后一个是隐藏参数,中间的才是你的参数。(就像Objective-C 方法第一个和第二个参数隐藏了)
void Profile__set_Coins (void* __this, int32_t value, const void* method);
你想调用这个方法,先要找到这个方法的地址,然后构建对应的方法签名(这就是在构造寄存器和栈)。第一个参数是对象的 this 指针,最后一个参数可以给 0 就行。
麻烦问一下:
public sealed class AClas : AClassSuper {
public byte[] AFunc() { } /// 需要调用的方法,dump.cs 里面的定义
}
1、我在ida 里面查看AFunc ,没有跟着this 和 MethodInfo,有些方法是有的, 这是为什么?
il2cpp:00000000022D4784
il2cpp:00000000022D4784 UnityEngine.Class$$AFunc ; CODE XREF: Facebook.Unity.CodelessCrawler$$
il2cpp:00000000022D4784 ; DATA XREF: __data:0000000003A014C0↓o
il2cpp:00000000022D4784
il2cpp:00000000022D4784 var_10 = -0x10
il2cpp:00000000022D4784 var_s0 = 0
il2cpp:00000000022D4784
il2cpp:00000000022D4784 STP X20, X19, [SP,#-0x10+var_10]!
il2cpp:00000000022D4788 STP X29, X30, [SP,#0x10+var_s0]
il2cpp:00000000022D478C ADD X29, SP, #0x10
il2cpp:00000000022D4790 ADRP X19, #byte_3A7F900@PAGE
il2cpp:00000000022D4794 LDRB W8, [X19,#byte_3A7F900@PAGEOFF]
il2cpp:00000000022D4798 TBNZ W8, #0, loc_22D47B4
2、这是我直接调用的AFunc代码, 通过打断点,我确定是已经走到AFunc 的里面去了,但是程序到这里就死了,不会走后面的代码,这个地方应该怎么设置lr、pc,可以让程序继续走下去
static uint8_t* (*my_Afunc)(); /// 这是函数定义,因为我看ida 里面没有this 和 method Info
/// 这是绑定
unsigned long my_Afunc_addr = _dyld_get_image_vmaddr_slide(i) + 0x22ab784;
my_Afunc = (uint8_t*(*)())my_Afunc_addr;
// 这是调用
uint8_t* data = my_Afunc();
if (data2) {/// 没有执行
printf("success");
} else {
printf("fail");
}
3、因为AFunc 没有this 指针,我手动将对象的地址弄到X0 里面去,我猜测this 指针就是在X0里面,是否可行?
__asm__ volatile ("stp x8, x9, [sp, #-16]!\n");
__asm__ volatile ("mov X0, %0 \n"
:
: "r" (objc)
);
__asm__ volatile ("ldp x8, x9, [sp], #16\n");
谢谢你!
就拿你这个 public byte[] AFunc() { } 方法来说
你至少这这样声明啊 static uint8_t* (*my_Afunc)(void* __this, const void* method);
你用 Perfare/Il2CppDumper: Unity il2cpp reverse engineer (github.com) 导出的文件有对应的 cpp 头文件声明,你看一下就知道了。
我就是用 Il2CppDumper 导出的dump.cs 文件看的代码,ida 也用 导出的script 文件跑过,确实没有后面的那个。
我对比了一下同一个类的其他方法,有些方法是会加上void *this 和 const MethodInfo *method,但这个确实没有
我也试过这样声明,也还是不行。
对汇编代码一步步debug下去,发现是Unity 内抛出异常了,所以没有正确的返回,谢谢你。
方便说一下是什么应用吗
这个不好意思,不太方便说出来
给你参考一下
/*
// Namespace:
public class Profile // TypeDefIndex: 2129
{
// Fields
private int m_coins; // 0x18
// Methods
// RVA: 0xFD7A4 Offset: 0xFD7A4 VA: 0x1000FD7A4
public void .ctor(string udid) { }
// RVA: 0xFE860 Offset: 0xFE860 VA: 0x1000FE860
public int get_Coins() { }
// RVA: 0xFE868 Offset: 0xFE868 VA: 0x1000FE868
public void set_Coins(int value) { }
}
// Namespace:
public class GUIShopCoinButton : GUIButton // TypeDefIndex: 2052
{
// Fields
public GUIShopTabButton productTabButton; // 0x60
public int productItemIndex; // 0x68
public GameObject clickEffectPrefab; // 0x70
public GameObject coinCountText; // 0x78
private GameObject m_clickEffect; // 0x80
// Methods
// RVA: 0xBC0D0 Offset: 0xBC0D0 VA: 0x1000BC0D0
public void .ctor() { }
// RVA: 0xB5858 Offset: 0xB5858 VA: 0x1000B5858
public void OnBuyFail() { }
// RVA: 0xBC0D8 Offset: 0xBC0D8 VA: 0x1000BC0D8
private void ShowClickEffect() { }
// RVA: 0xBC1AC Offset: 0xBC1AC VA: 0x1000BC1AC Slot: 4
public override void Click(Vector3 position) { }
// RVA: 0xBC2B0 Offset: 0xBC2B0 VA: 0x1000BC2B0 Slot: 7
protected override void OnActivate() { }
}
*/
#include <mach-o/dyld.h>
#include <substrate.h>
struct UnityEngine_Vector3_Fields {
float x;
float y;
float z;
};
struct UnityEngine_Vector3_o {
struct UnityEngine_Vector3_Fields fields;
};
void *profile_o;
int32_t (*Profile__get_Coins) (void* __this, const void* method);
void (*Profile__set_Coins) (void* __this, int32_t value, const void* method);
void (*Profile___ctor) (void* __this, void* udid, const void* method);
void new_Profile___ctor (void* __this, void* udid, const void* method) {
if (!profile_o) {
profile_o = __this;
}
Profile___ctor(__this, udid, method);
}
void (*GUIShopCoinButton__Click) (void* __this, struct UnityEngine_Vector3_o position, const void* method);
void new_GUIShopCoinButton__Click (void* __this, struct UnityEngine_Vector3_o position, const void* method) {
if (profile_o) {
int32_t coins = Profile__get_Coins(profile_o, NULL) + 1000;
Profile__set_Coins(profile_o, coins, NULL);
}
}
%ctor {
intptr_t slide = _dyld_get_image_vmaddr_slide(0);
Profile__get_Coins = (void *)(slide + 0x1000FE860);
Profile__set_Coins = (void *)(slide + 0x1000FE868);
MSHookFunction((void *)(slide + 0x1000FD7A4), (void *)new_Profile___ctor, (void **)&Profile___ctor);
MSHookFunction((void *)(slide + 0x1000BC1AC), (void *)new_GUIShopCoinButton__Click, (void **)&GUIShopCoinButton__Click);
}
谢谢你!