iOS小技能:lldb打印block参数签名

iOS逆向时经常会遇到参数为block类型,本文介绍一个lldb script,可快速打印出Objective-C方法中block参数的类型。,然后在 ~/.lldbinit 文件中添加下行内容:
command script import ~/zlldb/main.py,Objective-C type encodings
iOS小技能:lldb打印block参数签名
iOS小技能:lldb打印block参数签名,Objective-C method encodings,iOS小技能:lldb打印block参数签名,main.py,公号:iOS逆向,Chisel_fblldb.py_lldbinit,如果是逆向工作的话,没有代码,那可以断点到 objc_msgSend这行,执行命令 zblock 0x100588080 (block的地址传给 zblock命令),然后block的参数就出来了。,

前言

iOS逆向时经常会遇到参数为block类型,本文介绍一个lldb script,可快速打印出Objective-C方法中block参数的类型。

zblock <block-address> : print oc block signature, parameter -d for disassemble

I lldb打印block参数签名

1.1 install

cd ~
git clone git@github.com:zhangkn/zlldb.git

然后在 ~/.lldbinit 文件中添加下行内容:command script import ~/zlldb/main.py

1.2 使用

  1. 如果是逆向工作的话,没有代码,那可以断点到 objc_msgSend这行
  2. 执行命令 zblock 0x100588080 (block的地址传给 zblock命令),然后block的参数就出来了。
  3. 根据每一行的type encoding 对照苹果文档ocrtTypeEncodings即可知道block的参数都有什么。

https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html

由于Xcode11内置的lldb script开始默认Python3版本,facebook的chisel还有些支持问题(可能现在解决了)。zlldb就是把我自己常用的几个命令放到了这里,支持Python3(也就是最新版Xcode)。除了zblock外,还有几个简单的命令,大家可以参考README。

Objective-C type encodings iOS小技能:lldb打印block参数签名 iOS小技能:lldb打印block参数签名

Objective-C method encodings

iOS小技能:lldb打印block参数签名

1.3 Python script

main.py

zblock_print_block_signature

def zblock_print_block_signature(debugger, target, process, block_address):
    pointer_size = 8 if zblock_arch_for_target_is_64bit(target) else 4
    # print("pointer size = {0}".format(pointer_size))
    # print("block address = %x"%(block_address))

    flags_address = block_address + pointer_size	# The `flags` integer is after a pointer in the struct
    
    flags_error = lldb.SBError()
    flags = process.ReadUnsignedFromMemory(flags_address, 4, flags_error)

    if not flags_error.Success():
        print("Could not retrieve the block flags")
        return
    
    block_has_signature = ((flags & (1 << 30)) != 0)	# BLOCK_HAS_SIGNATURE = (1 << 30)
    block_has_copy_dispose_helpers = ((flags & (1 << 25)) != 0) # BLOCK_HAS_COPY_DISPOSE = (1 << 25)

    
    if not block_has_signature:
        print("The block does not have a signature")
        return
    
    block_descriptor_address = block_address + 2 * 4 + 2 * pointer_size	# The block descriptor struct pointer is after 2 pointers and 2 int in the struct
    
    block_descriptor_error = lldb.SBError()
    block_descriptor = process.ReadPointerFromMemory(block_descriptor_address, block_descriptor_error)
    if not block_descriptor_error.Success():
        print("Could not read the block descriptor struct")
        return
    
    signature_address = block_descriptor + 2 * pointer_size	# The signature is after 2 unsigned int in the descriptor struct
    if block_has_copy_dispose_helpers:
        signature_address += 2 * pointer_size	# If there are a copy and dispose function pointers the signature
    
    signature_pointer_error = lldb.SBError()
    signature_pointer = process.ReadPointerFromMemory(signature_address, signature_pointer_error)
    
    signature_error = lldb.SBError()
    signature = process.ReadCStringFromMemory(signature_pointer, 255, signature_error)

    if not signature_error.Success():
        print("Could not retrieve the signature")
        return
    
    print("Signature Address: 0x%x" %(signature_address))
    print("Signature String: %s" %(signature))

    escaped_signature = signature.replace('"', '\"')

    method_signature_cmd = 'po [NSMethodSignature signatureWithObjCTypes:"' + escaped_signature + '"]'
    debugger.HandleCommand(method_signature_cmd)

    docurl = 'https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtTypeEncodings.html'
    print('Type Encodings Ref: %s' % (docurl))

def zblock_disass_block_invoke_function(debugger, target, process, block_address, instruction_count):
    pointer_size = 8 if zblock_arch_for_target_is_64bit(target) else 4
    
    invoke_function_address = block_address + pointer_size + 2 * 4	# The `invoke` function is after one pointer and 2 int in the struct
    print("Invoke address: 0x%x" % (invoke_function_address))
    
    invoke_function_error = lldb.SBError()
    invoke_function_pointer = process.ReadPointerFromMemory(invoke_function_address, invoke_function_error)
    if not invoke_function_error.Success():
        print("Could not retrieve the block invoke function pointer")
        return
    
    disass_cmd = "disassemble --start-address " + str(invoke_function_pointer) + " -c " + str(instruction_count)
    debugger.HandleCommand(disass_cmd)

def zblock_arch_for_target_is_64bit(target):
    arch_64 = ['arm64', 'x86_64']
    arch = target.GetTriple().split('-')[0]
    return arch in arch_64

def cmd_zblock(debugger, command, result, internal_dict):
    cmd_args = shlex.split(command)

    usage = "usage: %prog arg1 [--disass -d] [--number-instructions -n]"
    parser = optparse.OptionParser(prog='zblock', usage=usage)
    parser.add_option('-d', '--disass', action='store_true', dest='disass', default=False)
    parser.add_option('-n', '--number-instructions', dest='numberinstructions', default=20)
    
    try:
        (options, args) = parser.parse_args(cmd_args)
    except:
        print("error parse parameter")
        return
    
    if len(args) == 0:
        print("You need to specify the name of a variable or an address")
        return
    
    number_instructions = options.numberinstructions
    should_disass = options.disass
    
    target = debugger.GetSelectedTarget()
    process = target.GetProcess()
    thread = process.GetSelectedThread()
    frame = thread.GetSelectedFrame()

    variable_arg = args[0]
    address = int(variable_arg,0)
    if address == 0: 
        print("invalid address")
        return

    print("Block address: 0x%x" % (address))
    
    zblock_print_block_signature(debugger, target, process, address)

    if should_disass:
        zblock_disass_block_invoke_function(debugger, target, process, address, number_instructions)

see also

公号:iOS逆向

Chisel_fblldb.py_lldbinit

Chisel is a collection of LLDB commands to assist debugging iOS apps.

https://github.com/kunnan/kunnan.github.io/blob/master/_posts/Debug/2018-07-07-Chisel_fblldb.py_lldbinit.md

文章版权声明

 1 原创文章作者:9268,如若转载,请注明出处: https://www.52hwl.com/37452.html

 2 温馨提示:软件侵权请联系469472785#qq.com(三天内删除相关链接)资源失效请留言反馈

 3 下载提示:如遇蓝奏云无法访问,请修改lanzous(把s修改成x)

 免责声明:本站为个人博客,所有软件信息均来自网络 修改版软件,加群广告提示为修改者自留,非本站信息,注意鉴别

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023年7月15日
下一篇 2023年7月15日