已知有一个类方法,用hook OC方法的写法,能hook到,现在已经能正常断到这个新写的函数里边,下边是我的写法
void newFakeMethod2( id self , SEL _cmd ){
orgFakeMethod2( self , _cmd );
}
然后看下边ida下的汇编,这里原函数里边的汇编代码,x20最开始是self,
ADRP X8, #0x2DBB000
LDR X8, [X8,#0xF70]
LDR X20, [X20,X8]
这是swift源码,这里边的self.textInputNode应该算是这个类的全局变量了。上边汇编代码最后一行就是获取的这个值。
@objc func sendButtonPressed() {
if let textInputNode = self.textInputNode, let presentationInterfaceState = self.presentationInterfaceState, let editMessage = presentationInterfaceState.interfaceState.editMessage, let inputTextMaxLength = editMessage.inputTextMaxLength {
let textCount = Int32(textInputNode.textView.text.count)
let remainingCount = inputTextMaxLength - textCount
if remainingCount < 0 {
textInputNode.layer.addShakeAnimation()
self.hapticFeedback.error()
return
}
}
self.sendMessage()
}
提问:我hook的那段代码,怎么才能获取self.textInputNode的值,毕竟是swift类,结构我断下来看了,跟OC有些差别,用id tmp = [self valueForKey:@“textInputNode”]; 根本获取不到,提示未定义。
最终的解决方案可能采用地址运算的方式。在第二行汇编代码下了断点,最后x8里边存储的是0x480,用self的地址加到0x480就是我需要的类属性的地址了,可不知道地址能不能转成类去操作。
rEcover
(rEcover)
2
TelegramUI, ldr x20, [x20, x8] ,这句是读取 x20+x8 内存处,8字节。
朋友,那我怎么写OC代码获取x20的值?
因为我hook到了这个方法。我直接写汇编?
Runtime 中与成员变量和属性相关的函数有很多,这里罗列出一些常用的方法:
-
Ivar class_getClassVariable(Class cls, const char *name)
,返回指定类的指定名字的成员变量;
-
Ivar *class_copyIvarList(Class cls, unsigned int *outCount)
,返回指定类的成员变量列表。调用后需要自己 free();
-
BOOL class_addIvar(Class cls, const char *name, size_t size, uint8_t alignment, const char *types)
,给指定的类添加成员变量。这个函数只能在 objc_allocateClassPair()
和 objc_registerClassPair()
之间调用,并且不能为一个已经存在的类添加成员变量;
-
id object_getIvar(id obj, Ivar ivar)
,获得对象的指定成员变量的值。速度比 object_getInstanceVariable()
快;
-
void object_setIvar(id obj, Ivar ivar, id value)
,设置对象指定成员变量的值。速度比 object_setInstanceVariable()
快;
-
Ivar object_getInstanceVariable(id obj, const char *name, void **outValue)
,获取指定名字的成员变量的值;
-
Ivar object_setInstanceVariable(id obj, const char *name, void *value)
,设置指定名字成员变量的值;
-
const char *ivar_getName(Ivar v)
,获取成员变量名;
-
const char *ivar_getTypeEncoding(Ivar v)
,获取成员变量的类型编码;
-
ptrdiff_t ivar_getOffset(Ivar v)
,获取成员变量的偏移量;
- ``objc_property_t class_getProperty(Class cls, const char *name)`, 获取指定类指定名字的属性;
-
objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
, 获取指定类的属性列表。调用后需要自己 free();
-
BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
, 给指定的类添加属性;
-
void class_replaceProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
,替代指定类的属性;
-
const char *property_getName(objc_property_t property)
,获取属性名;
-
const char *property_getAttributes(objc_property_t property)
,获取属性特性描述;
-
objc_property_attribute_t *property_copyAttributeList(objc_property_t property, unsigned int *outCount)
,获取属性特性列表。调用后需要自己 free();
-
char *property_copyAttributeValue(objc_property_t property, const char *attributeName)
,获取属性特性值。调用后需要自己 free();
1 个赞
是self,后来跟x8运算了,我贴出了swift源码,您可以看一下。我已经hook到了这个方法,怎么才能获取运算后的x20.用oc的写法id tmp = [self valueForKey:@“textInputNode”];会报错[<TelegramUI.ChatTextInputPanelNode 0x1079fc000> valueForUndefinedKey:,所以不能用这个写法
开源的你自己调试一下呗,在函数开头下个断点,进汇编看x20到底是个啥
是那个类,x20未运算前,是那个self,就是类实例,运算后就成了类里边的一个属性。但是swift的类结构有点看不懂,跟OC还是不一样,需要的那个类属性,肉眼看是看不到的。非得这样加一下才能看得到。不知道怎么写,难不成我用汇编写。
yangyss
(yangyss)
9
hook的本质是什么?
知道hook本质了,你就知道怎么写了。
类和实力对象,本质又是什么?
知道了 类和实例对象的本质,你就知道怎么访问了。
高屋建瓴,是没办法知道本质的…
探求本质,需要去撸汇编,撸内存分配的…
如果别人的工具不适合你,你基本就蒙圈。
作为一个逆向的过来人,我想说的是,逆向的基础很重要。
不外乎看得懂汇编,能汇编和高层代码互相翻译,掌握不同类型hook的本质 <=== 这些都是基本功
而熟悉各种语言,能加速你逆向此语言写的app,属于逆向技术应用方向了。
因此,你缺的是基本功。
ADRP X8, #0x2DBB000
LDR X8, [X8,#0xF70]
LDR X20, [X20,X8]
当别的工具 你感觉不对的时候,你需要看汇编。
每一句占几个字节?hook的原理是什么?hook的代码占几个字节?
hook代码中,怎么读寄存器?hook代码中,怎么保护原有的上下文?
hook后,怎么回到下一条指令?
1,每一个知识点,都有不少的东西去探讨。
2,当你从 高级语言层 来探讨 为什么的时候,说白了,就是空中楼阁。
3,我也只能给你提供点方向。基本功的东西,问别人不如自己写个demo,去敲敲代码,然后从我说的几个方向去思考下。
跳转表的hook,我就不说了,主要是函数地址的替换<保证替换的函数原型,和被替换的一样就行>。
inline hook <这个才是逆向中运用最多的>:
1,对于inline hook,你需要构造的是一个跳转。这个跳转,让pc指向你的 hook 函数。比如 b xxxxxx
<asm下的是 jmp xxxxx>
2,假若跳转指令长度为4,那么你就需要破坏4个字节,来填冲你的 b xxxxx。<远跳,近跳,到时候,需要具体考虑>
3,破坏了指令了,是不是需要保存 被你破坏的指令?答案是必然的…不保存的话,程序必然崩溃。
4,在你跳转函数地方,是不是直接读 所有寄存器了?这就是 …<如果函数调用规则定了,参数对应的寄存器也是定的>,你可以操作 content<hook处的上下文>。
5,然后就是执行你的代码了…
6,执行完你的代码,是不是要还原 上下文?
7,最后是不是需要执行一下,被你破坏的指令?
8,其实这才是最后一个事情,跳转到被你破坏的执行的 下一行!
不论什么语言的hook 都这么写… 没啥难的…
说道汇编了,基础的东西…emmmmmm ,我组织下语言…
感觉还是没啥可说的,写demo,然后读懂,然后翻译。最后看到汇编,就知道高级语言是啥样子的,看到高级语言,就知道汇编大概是啥样子…
内存分配:
1,内存,就是一块连续的空间,调用系统函数分配的内存,都是连续的.
2,对象实例和结构体,一个叼毛样子,都是一块固定大小且连续的内存…
3,成员是啥呢?就是内存中值。怎么读这些值呢?那就是对齐方式<1字节对齐,2字节对齐,还是4/8字节对齐(因为效率问题,大部分都是当前cpu位的对齐)>,以及读取长度<是读1个字节,还是xxx个字节…>(读一个字节是 char,读2个字节是…字,读4个字节是 dword,读8个字节<64位下>,可以是qword,可以是指针…管那么多,就当qword了…)
回头看下你这个汇编…
ADRP X8, #0x2DBB000
LDR X8, [X8,#0xF70]
LDR X20, [X20,X8]
x20初始值:应该是一个对象的首地址<基本都是面向对象编程> [定义 obj = x20]
x8 : 是一个偏移量,基于 某个地址<对象的>偏移量 [定义 xxoffset = x8 ]
x20最后的值: 不就是从 obj 的 xxoffset 中读取 x20的长度<64位寄存器,qword长度>,8个字节的值,然后存到 x20寄存器么…
其他的我看不到了…
4 个赞
你是想hook这个值吗?我记得我之前也问过这样的问题,纯swift类的属性,方法已经被编译成静态方法了,类似C语言函数了,如果你是想hook self.textInputNode的值 只能找这个属性对应的C方法了 然后inlinehook 继续按hook OC的方法是不可能的
qsmoon
13
大佬,你说inline hook是逆向中应用最多的,不过感觉网上的资料很少的样子,有相应的学习资料推荐的吗?