0基础学习ollvm反混淆之-0x01-trace 汇编

碰到个混淆

c-stalker


// typedef void (* GumEventSinkCallback) (const GumEvent * event, GumCpuContext * cpu_context, gpointer user_data);
static void event_sink(const GumEvent* event, GumCpuContext const* cpu_context, gpointer user_data) {
//    g_print("called event_sink %d \n", event->type);
    
//    GUM_NOTHING     = 0,
//    GUM_CALL        = 1 << 0,
//    GUM_RET         = 1 << 1,
//    GUM_EXEC        = 1 << 2,
//    GUM_BLOCK       = 1 << 3,
//    GUM_COMPILE     = 1 << 4,
    switch (event->type) {
        case GUM_NOTHING:
            g_print("called event_sink GUM_NOTHING \n");
            break;
            
        case GUM_CALL:
            g_print("called event_sink GUM_CALL \n");
            break;
        case GUM_RET:
            g_print("called event_sink GUM_RET \n");
            break;
        case GUM_EXEC:
            g_print("called event_sink GUM_EXEC \n");
        case GUM_BLOCK:
            g_print("called event_sink GUM_BLOCK \n");
            break;
        case GUM_COMPILE:
            g_print("called event_sink GUM_COMPILE\n");
            break;
        default:
            break;
    }
}
static void
on_enter_sub (GumInvocationContext * ic,
          gpointer user_data)
{
    
   
    GumStalkerTransformer* transformer = gum_stalker_transformer_make_from_callback( print_insn, NULL, NULL);


    g_print("ic->backend->get_thread_id(ic) : %lu \n",ic->backend->get_thread_id(ic));
    g_print("gum_process_get_current_thread_id : %lu \n",gum_process_get_current_thread_id());


    GumEventSink *sink = gum_event_sink_make_from_callback(    GUM_CALL | GUM_RET, (GumEventSinkCallback)event_sink, NULL, NULL);

    gum_stalker_follow(stalker, ic->backend->get_thread_id(ic), transformer, sink);



    
}

static void
on_leave_sub (GumInvocationContext * ic,
          gpointer user_data)
{
//  int result  = GPOINTER_TO_INT (gum_invocation_context_get_return_value (ic));
    
    

    gum_stalker_unfollow(stalker,ic->backend->get_thread_id(ic));

    g_print (" on_leave_sub ");
//    g_print("flag : %d \n", user_data );
}



void print_insn(GumStalkerIterator* iterator, GumStalkerOutput* output, gpointer user_data) {
    const cs_insn* instr;
    while (gum_stalker_iterator_next(iterator, &instr)) {
        
        g_print("Inst Addr 0x%llx\t: \t %s   \t %s\n", instr->address, instr->mnemonic, instr->op_str);
        gum_stalker_iterator_keep(iterator);
    }
}

js-stalker

function teststalker() {
    let baseAddr = 0x7FA30;
    try {
        
        var targetAddress =  get_func_addr('TargetModule', baseAddr);
        if (targetAddress) {
            Interceptor.attach(targetAddress, {
                onEnter: function(args) {
                    console.log('Hooked function at { ' + baseAddr.toString(16) +  '}: ');
             
                           console.log("threadId " + this.threadId);
                           Stalker.follow(this.threadId, {
                            events: {
                                call: true, // CALL instructions: yes please            
                                ret: true, // RET instructions
                                exec: false, // all instructions: not recommended as it's
                                block: false, // block executed: coarse execution trace
                                compile: false // bl
                            },
                            
                            transform : (iterator) =>{
                                    let instruction = iterator.next();
                                    
                                    const startAddress = instruction.address;
                                    const isAppCode = startAddress.compare(targetAddress) >= 0;
                                    
                                    do {
                                        if (isAppCode ) {
                                       
                                        
                         
                                            
                                            console.log(instruction);   
                                            console.log(instruction.mnemonic + " " + instruction.opStr) ;   
                                            // console.log();   

                                        }
                                    
                                        iterator.keep();
                                    } while ((instruction = iterator.next()) !== null);
                                },
                                
                        });

                           
                           console.log(' '   + ' called from:\n' +
                            							Thread.backtrace(this.context, Backtracer.ACCURATE)
                            							.map(DebugSymbol.fromAddress).join('\n') + '\n');
            
                    
                },
                onLeave: function(retval) {
                 
                    Stalker.unfollow();
                    // retval.replace(this.returnValue);

                  
                    console.log('Hooked function at + ' + baseAddr + '  + ' + 'retval'  + retval.toString());
                }
            });
        } else {
            console.warn('Address not found: ' + baseAddr);
        }
    } catch (e) {
        console.error('Error hooking address: ' + baseAddr, e);
    }
}

lldb-trace

Chomper

Version:1.0 StartHTML:0000000105 EndHTML:-9223372036854775704 StartFragment:-9223372036854775704 EndFragment:-9223372036854775704
import logging
import os
import uuid

from chomper import Chomper
from chomper.const import ARCH_ARM64, OS_IOS
from chomper.objc import ObjC
from chomper.utils import pyobj2nsobj

base_path = os.path.abspath(os.path.dirname(__file__))

log_format = "%(asctime)s - %(name)s - %(levelname)s: %(message)s"
logging.basicConfig(
    format=log_format,
    level=logging.INFO,
)

logger = logging.getLogger(__name__)


def hook_skip(uc, address, size, user_data):
    pass


def hook_retval(retval):
    def decorator(uc, address, size, user_data):
        return retval

    return decorator


def hook_ns_bundle(emu):
    executable_path = f"/var/containers/Bundle/Application/{uuid.uuid4()}/com.ceair.b2m/target"

    bundle_info = {
        "CFBundleShortVersionString": "9.4.7",
        "CFBundleExecutable": executable_path,
    }

    emu.add_interceptor("-[NSBundle initWithPath:]", hook_skip)
    emu.add_interceptor("-[NSBundle bundleIdentifier]", hook_retval(pyobj2nsobj(emu, "com.ceair.b2m")))
    emu.add_interceptor("-[NSBundle executablePath]", hook_retval(pyobj2nsobj(emu, executable_path)))
    emu.add_interceptor("-[NSBundle infoDictionary]", hook_retval(pyobj2nsobj(emu, bundle_info)))


def main():
    emu = Chomper(
        arch=ARCH_ARM64,
        os_type=OS_IOS,
        logger=logger,
        rootfs_path=os.path.join(base_path, "ios/rootfs"),
        enable_ui_kit=True,
    )

    objc = ObjC(emu)

    hook_ns_bundle(emu)

    # Skip a file operation
    emu.add_interceptor("_fopen", hook_retval(0))

    libszstone = emu.load_module(
        os.path.join(base_path, "ios/apps/com.www.yuzhouheike/target"),
        exec_init_array=True,
        trace_inst=True,
        trace_symbol_calls=True
        )

    with objc.autorelease_pool():
        
        

        result_size = emu.call_address(libszstone.base + 0x57188C)

        logger.info("PRMShieldEventManage: %d",result_size)


if __name__ == "__main__":
    main()

参考链接

2 个赞

请问stalker脚本稳定吗,尤其在大型混淆的代码场景。我之前用的时候遇到过中途crash

可以用c版本的试试.我也刚学

c 版本的咋使用呢,大佬

帖子里面有代码

这几个脚本只处理了指令路径 应该正确率不高 Chomper 对条件指令应该无效 并且unicron的内存分析UC_HOOK_MEM_WRITE|UC_HOOK_MEM_READ目前在arm64上面有bug不能用 只能打印出满足条件的执行指令 反混淆或者其他的指令分析 你必须要处理branch condition stack 所以仅仅靠指令分析是完成不了这些工作的

2 个赞

那应该如何处理branch condition stack呢,有相关学习资料推荐吗

为什么一定要有现成的资料 哈哈 其实前人总结的cfg cff加密方法并没有特定的解密方法 这些代码解密的方案最终是需要分割成基本的功能去实现 简单来说 如果你能把branch condition stack var指令列出来 那已经完成了30% 如果你能把相关的指令列出来那已经完成了60% 剩下的40%无非解决正确率和自动分析效率的问题 结果因人而异 这才是开放的对抗研究方法