逆向中获取 Block callback 的参数和返回值

一行代码获取Block的签名和虚拟内存地址:

  NSString *blockDescription = [ZLJBlockPrinter printBlock:_shareBlock];
  NSLog(@"%@",blockDescription);

 返回效果

kSignature:<NSMethodSignature: 0x281aaa9c0>
    number of arguments = 4
    frame size = 224
    is special struct return? NO
    return value: -------- -------- -------- --------
        type encoding (v) 'v'
        flags {}
        modifiers {}
        frame {offset = 0, offset adjust = 0, size = 0, size adjust = 0}
        memory {offset = 0, size = 0}
    argument 0: -------- -------- -------- --------
        type encoding (@) '@?'
        flags {isObject, isBlock}
        modifiers {}
        frame {offset = 0, offset adjust = 0, size = 8, size adjust = 0}
        memory {offset = 0, size = 8}
    argument 1: -------- -------- -------- --------
        type encoding (B) 'B'
        flags {}
        modifiers {}
        frame {offset = 8, offset adjust = 0, size = 8, size adjust = -7}
        memory {offset = 0, size = 1}
    argument 2: -------- -------- -------- --------
        type encoding (i) 'i'
        flags {isSigned}
        modifiers {}
        frame {offset = 16, offset adjust = 0, size = 8, size adjust = -4}
        memory {offset = 0, size = 4}
    argument 3: -------- -------- -------- --------
        type encoding (@) '@"NSString"'
        flags {isObject}
        modifiers {}
        frame {offset = 24, offset adjust = 0, size = 8, size adjust = 0}
        memory {offset = 0, size = 8}
            class 'NSString'
返回显示4个参数  要减去1个 return 



所以下面得出 callback 参数为:

^(BOOL isok, int code, NSString*msg) {

}

查看官方文档访问点击查看更多对照表信息

//
//  ZLJPrinter.h
//  SMS
//
//  Created by Mu on 2019/8/1.
//

#import <Foundation/Foundation.h>
#import <mach-o/dyld.h>
#import <mach/mach.h>

NS_ASSUME_NONNULL_BEGIN

@interface ZLJPrinter : NSObject

+ (NSString *)printBlock:(id)aBlock;
+ (NSString *)callStackSymbolsLocateInImages:(NSArray <NSString *>*)images;

@end

NS_ASSUME_NONNULL_END


/* block 内存结构
 struct Block_literal_1 {
 void *isa; //16byte initialized to &_NSConcreteStackBlock or &_NSConcreteGlobalBlock
 int flags; //8byte
 int reserved; //8byte
 void (*invoke)(void *, ...); //16byte
 struct Block_descriptor_1 { //16byte
 unsigned long int reserved;         //16byte NULL
 unsigned long int size;         //16byte sizeof(struct Block_literal_1)
 // optional helper functions
 void (*copy_helper)(void *dst, void *src);     //16byte IFF (1<<25)
 void (*dispose_helper)(void *src);             //16byte IFF (1<<25)
 // required ABI.2010.3.16
 const char *signature;                         //16byte IFF (1<<30)
 } *descriptor;
 // imported variables
 };
 
 struct BlockLiteral {
 void *isa;
 int flags;
 int reserved;
 void (*invoke)(void *, ...);
 struct BlockDescriptor *descriptor;
 };
 
 struct BlockDescriptor {
 unsigned long int reserved;
 unsigned long int size;
 void (*copy_helper)(void *dst, void *src);
 void (*dispose_helper)(void *src);
 const char *signature;
 };
 
 */
//
//  ZLJPrinter.m
//  SMS
//
//  Created by Mu on 2019/8/1.
//

#import "ZLJPrinter.h"

@implementation ZLJPrinter

+ (NSString *)callStackSymbolsLocateInImages:(NSArray <NSString *>*)images{
    
    NSArray <NSString *>*preSetImages = [@[
                                           @"libdyld.dylib",
                                           @"UIKit",
                                           @"GraphicsServices",
                                           @"CoreFoundation",
                                           @"Foundation",
                                           ] mutableCopy];
    
    NSMutableDictionary <NSString *, NSNumber *>*baseAddrDic = [[NSMutableDictionary alloc]init];
    
    for(int i = 0; i < _dyld_image_count(); i++)
    {
        intptr_t  base_addr = _dyld_get_image_vmaddr_slide(i);
        const char *name = _dyld_get_image_name(i);
        NSString *nameStr = [NSString stringWithUTF8String:name];
        
        if ([images containsObject:[nameStr lastPathComponent]] ||
            [preSetImages containsObject:[nameStr lastPathComponent]]) {
            [baseAddrDic setObject:@(base_addr) forKey:[nameStr lastPathComponent]];
        }
    }
    
    NSArray <NSString *>*syms = [NSThread  callStackSymbols];
    
    NSMutableString *retStr = [[NSMutableString alloc]init];
    [retStr appendString:@"\n\n/***ZLJ CallStackSymbols Start***/\n"];
    for (NSString *sym in syms) {
        
        NSMutableArray <NSString *>*symUnits = [[sym componentsSeparatedByString:@" "] mutableCopy];
        while ([symUnits containsObject:@""]) {
            [symUnits removeObject:@""];
        }
        
        if (symUnits.count >= 3 && [symUnits[2] hasPrefix:@"0x"]) {
            
            char *symVMAddrStr = (char *)symUnits[2].UTF8String;
            char *endPtr;
            NSInteger symVMAddr = strtol(symVMAddrStr, &endPtr, 16);
            
            if ([baseAddrDic.allKeys containsObject:symUnits[1]]) {
                NSInteger symFileAddr = symVMAddr - [baseAddrDic objectForKey:symUnits[1]].integerValue;
                [retStr appendFormat:@"%@  symFileAddr 0x%lx\n", sym, symFileAddr];
            }else{
                [retStr appendFormat:@"%@\n", sym];
            }
            
        }else{
            [retStr appendFormat:@"%@\n", sym];
        }
    }
    [retStr appendString:@"/***ZLJ CallStackSymbols End***/\n\n"];
    
    NSLog(@"%@",retStr);
    
    return retStr;
}


+ (NSString *)printBlock:(id)aBlock{
    
    if (!([aBlock isKindOfClass:NSClassFromString(@"__NSGlobalBlock__")] ||
          [aBlock isKindOfClass:NSClassFromString(@"__NSMallocBlock__")] ||
          [aBlock isKindOfClass:NSClassFromString(@"__NSStackBlock__")]    )) {
        return @"ZLJBlockPrinter Error: Not A Block!";
    }
    
    uint64_t blockInMemory[4];      //block 在内存中的前4个uint64_t
    uint64_t descriptor[5];         //block的descriptor 在内存中的前5个uint64_t
    char *signatureCStr;
    NSMethodSignature *blockSignature;
    
    void *aBlockPtr = (__bridge void *)(aBlock);
    memcpy(blockInMemory, (void *)aBlockPtr, sizeof(blockInMemory));
    memcpy(descriptor, (void *)blockInMemory[3], sizeof(descriptor));
    
    BOOL hasSignature = ((blockInMemory[1] & 0x00000000FFFFFFFF)  & (1 << 30)) != 0;
    if (!hasSignature) {
        return @"ZLJBlockPrinter: Block Do Not Have Signature!";
    }
    
    BOOL hasCopyDisposeHelper = ((blockInMemory[1] & 0x00000000FFFFFFFF)  & (1 << 25)) != 0;
    
    if (hasCopyDisposeHelper) {
        signatureCStr = (char *)descriptor[4];
    }else{
        signatureCStr = (char *)descriptor[2];
    }
    blockSignature = [NSMethodSignature signatureWithObjCTypes:signatureCStr];
    
    NSString *retStr = [NSString stringWithFormat:@"\n%@\nBlockVmaddrSlide:0x%llx\nBlockSignature:%@",
                        aBlock,
                        blockInMemory[2],
                        blockSignature.debugDescription];
    NSLog(@"%@",retStr);
    
    return retStr;
}

//+ (NSString *)printBlock:(id)aBlock inImage:(nullable NSString *)imageName{
//
//    if (!([aBlock isKindOfClass:NSClassFromString(@"__NSGlobalBlock__")] ||
//          [aBlock isKindOfClass:NSClassFromString(@"__NSMallocBlock__")] ||
//          [aBlock isKindOfClass:NSClassFromString(@"__NSStackBlock__")]    )) {
//        return @"ZLJBlockPrinter Error: Not A Block!";
//    }
//
//    uint64_t blockInMemory[4];      //block 在内存中的前4个uint64_t
//    uint64_t descriptor[5];         //block的descriptor 在内存中的前5个uint64_t
//    char *signatureCStr;
//    NSMethodSignature *blockSignature;
//
//    void *aBlockPtr = (__bridge void *)(aBlock);
//    memcpy(blockInMemory, (void *)aBlockPtr, sizeof(blockInMemory));
//    memcpy(descriptor, (void *)blockInMemory[3], sizeof(descriptor));
//
//    BOOL hasSignature = ((blockInMemory[1] & 0x00000000FFFFFFFF)  & (1 << 30)) != 0;
//    if (!hasSignature) {
//        return @"ZLJBlockPrinter: Block Do Not Have Signature!";
//    }
//
//
//    BOOL hasCopyDisposeHelper = ((blockInMemory[1] & 0x00000000FFFFFFFF)  & (1 << 25)) != 0;
//
//    if (hasCopyDisposeHelper) {
//        signatureCStr = (char *)descriptor[4];
//    }else{
//        signatureCStr = (char *)descriptor[2];
//    }
//    blockSignature = [NSMethodSignature signatureWithObjCTypes:signatureCStr];
//
//
//    uint64_t block_file_slide = 0;
//    if (imageName.length && [aBlock isKindOfClass:NSClassFromString(@"__NSGlobalBlock__")]) {
//        NSInteger image_vmaddr_slide = 0;
//        for(int i = 0; i < _dyld_image_count(); i++)
//        {
//            const char *name = _dyld_get_image_name(i);
//            NSString *nameStr = [NSString stringWithUTF8String:name];
//            if ([nameStr containsString:imageName]) {
//                image_vmaddr_slide = _dyld_get_image_vmaddr_slide(i);
//                break;
//            }
//        }
//        block_file_slide = blockInMemory[2] - image_vmaddr_slide;
//    }
//
//    NSString *ret = nil;
//    if (imageName.length && [aBlock isKindOfClass:NSClassFromString(@"__NSGlobalBlock__")]) {
//        ret = [NSString stringWithFormat:@"\n%@\nBlockVmaddrSlide(Check This Address In LLDB):0x%llx\nBlockFileSlide(Jump To This Address In IDA):0x%llx\nBlockSignature:%@", [aBlock class], blockInMemory[2], block_file_slide, blockSignature.debugDescription];
//    }else{
//        ret = [NSString stringWithFormat:@"\n%@\nBlockVmaddrSlide(Check This Address In LLDB):0x%llx\nBlockSignature:%@", aBlock, blockInMemory[2], blockSignature.debugDescription];
//    }
//
//    return ret;
//}


@end
发布了272 篇原创文章 · 获赞 123 · 访问量 109万+

猜你喜欢

转载自blog.csdn.net/qq_21051503/article/details/105283961
今日推荐