首页
社区
课程
招聘
[原创]某手游xqtd的简单分析
发表于: 2023-5-30 22:30 38208

[原创]某手游xqtd的简单分析

2023-5-30 22:30
38208

闲着没事,看到有新游出来,于是简单的分析学习一下。
由于时间和水平有限,本文会存在诸多不足,欢迎补充指正。

样本:xqtd
加固:mtp
工具:ida、010、jadx、frida

第一种,流程很清晰,比较好处理

ida脚本,如遇到报错需要修改脚本

处理前

处理后

第二种,有点像做了流水线优化,不太好处理

在方法sub_985D4反射调用isDebuggerConnected

在方法sub_9843C使用socket连接了127.0.0.1:23946

在方法sub_98B34遍历maps查找frida-gadgetfrida-agent

在方法sub_994A8使用socket连接了127.0.0.1:27402

记得比较流水账,大佬们将就看。

 
import idautils
import idc
import idaapi
import ida_ua
from keystone import *
 
g_reg = [0] * 40
reg_base = 129
g_cond_info = list()
ldr_reg = -1
add_reg = -1
 
ks = keystone.Ks(keystone.KS_ARCH_ARM64, keystone.KS_MODE_LITTLE_ENDIAN)
 
def get_opcode(ea):
    opcode = None
    disasm = idc.GetDisasm(ea)
    if disasm.find('LT') != -1:
        opcode = 'blt'
    elif disasm.find('EQ') != -1:
        opcode = 'beq'
    elif disasm.find('CC') != -1:
        opcode = 'bcc'
    elif disasm.find('GT') != -1:
        opcode = 'bgt'
    elif disasm.find('NE') != -1:
        opcode = 'bne' 
    elif disasm.find('GE') != -1:
        opcode = 'bge' 
    elif disasm.find('HI') != -1:
        opcode = 'bhi' 
    return opcode
 
 
def do_patch(patch_1, patch_2, opcode, cond_jmp_addr, uncond_jmp_addr):
    print("patch_1=0x%x patch_1=0x%x opcode=%s cond_jmp_addr=0x%x uncond_jmp_addr=0x%x" % (patch_1, patch_2, opcode, cond_jmp_addr, uncond_jmp_addr))
 
    jump_offset = " ({:d})".format(cond_jmp_addr - patch_1)
    repair_opcode = opcode + jump_offset
    encoding, count = ks.asm(repair_opcode)
    idaapi.patch_byte(patch_1, encoding[0])
    idaapi.patch_byte(patch_1 + 1, encoding[1])
    idaapi.patch_byte(patch_1 + 2, encoding[2])
    idaapi.patch_byte(patch_1 + 3, encoding[3])
 
    jump_offset = " ({:d})".format(uncond_jmp_addr - patch_2)
    repair_opcode = 'b' + jump_offset
    encoding, count = ks.asm(repair_opcode)
    idaapi.patch_byte(patch_2, encoding[0])
    idaapi.patch_byte(patch_2 + 1, encoding[1])
    idaapi.patch_byte(patch_2 + 2, encoding[2])
    idaapi.patch_byte(patch_2 + 3, encoding[3])
 
 
def do_deobf(ea):
    # 获取跳转条件
    opcode = get_opcode(ea)
    if opcode is None:
        print("opcode:unknown opcode 0x%x" % ea)
        return ea
 
    # 获取跳转信息
    cond_reg = -1
    uncond_reg = -1
    cond_data = -1
    uncond_data = -1
    mnem = idc.ida_ua.ua_mnem(ea)
    if mnem == 'CSEL':
        cond_reg = idc.get_operand_value(ea, 1)
        uncond_reg = idc.get_operand_value(ea, 2)
    elif mnem == 'CSET':
        cond_data = 1
        uncond_data = 0
    ea = idc.next_head(ea)
 
    # 获取LDR寄存器
    ldr_reg = -1
    lsl_value = -1
    mnem = idc.ida_ua.ua_mnem(ea)
    if mnem == 'LSL':
        lsl_value = idc.get_operand_value(ea, 2)
        ea = idc.next_head(ea)
        mnem = idc.ida_ua.ua_mnem(ea)
 
    if mnem != 'LDR':
        print("LDR:0x%x -> %s" % (ea, mnem))
        return ea
 
    operand_type = idc.get_operand_type(ea, 1)
    if operand_type == idc.o_phrase:
        insn = ida_ua.insn_t()
        ida_ua.decode_insn(insn, ea)
        ldr_reg = insn.Op2.reg
        if lsl_value == -1:
            lsl_value = insn.Op2.value
    else:
        return ea
    ea = idc.next_head(ea)
 
    # 获取ADD寄存器
    mnem = idc.ida_ua.ua_mnem(ea)
    if mnem == 'MOV':
        ea = idc.next_head(ea)
        mnem = idc.ida_ua.ua_mnem(ea)
 
    if mnem != 'ADD':
        print("ADD:0x%x -> %s" % (ea, mnem))
        return ea
    op_3 = idc.print_operand(ea, 2)
    op_3 = op_3[1:]
    ea = idc.next_head(ea)
 
    # 进行patch
    mnem = idc.ida_ua.ua_mnem(ea)
    if mnem != 'BR':
        print("BR:0x%x -> %s" % (ea, mnem))
        return ea
 
    #print('1 = %d 2 = %d 3 = 0x%x' % (g_reg[ldr_reg - reg_base],  g_reg[cond_reg - reg_base], g_reg[int(op_3)]))
    if cond_data != -1 and uncond_data != -1:
        print(lsl_value)
        cond_jmp_addr  = (idc.get_qword(g_reg[ldr_reg - reg_base] + (cond_data << lsl_value)) + g_reg[int(op_3)]) & 0xffffffffffffffff
        uncond_jmp_addr = (idc.get_qword(g_reg[ldr_reg - reg_base] + (uncond_data << lsl_value)) + g_reg[int(op_3)]) & 0xffffffffffffffff
    else:
        cond_jmp_addr   = (idc.get_qword(g_reg[ldr_reg - reg_base] + (g_reg[cond_reg - reg_base] << lsl_value)) + g_reg[int(op_3)]) & 0xffffffffffffffff
        uncond_jmp_addr = (idc.get_qword(g_reg[ldr_reg - reg_base] + (g_reg[uncond_reg - reg_base] << lsl_value)) + g_reg[int(op_3)]) & 0xffffffffffffffff
    do_patch(idc.prev_head(ea), ea, opcode, cond_jmp_addr, uncond_jmp_addr)
    return ea
 
 
def deobf(ea):
    off_reg = -1
    off_data = -1
    while True:
        mnem = idc.ida_ua.ua_mnem(ea)
        if mnem == 'RET':
            break
        elif mnem == 'MOV':
            op_1_type = idc.get_operand_type(ea, 0)
            op_2_type = idc.get_operand_type(ea, 1)
            if (op_1_type == idc.o_reg) and (op_2_type == idc.o_imm):
                op_1 = idc.get_operand_value(ea, 0)
                op_2 = idc.get_operand_value(ea, 1)
                g_reg[op_1 - reg_base] = op_2
        elif mnem == 'MOVK':
            op_1_type = idc.get_operand_type(ea, 0)
            op_2_type = idc.get_operand_type(ea, 1)
            op_3_type = idc.get_operand_type(ea, 2)
            if (op_1_type == idc.o_reg) and (op_2_type == idc.o_imm):
                op_1 = idc.get_operand_value(ea, 0)
                op_2 = idc.get_operand_value(ea, 1)
                g_reg[op_1 - reg_base] = (op_2 << 16) | (g_reg[op_1 - reg_base] & 0xffff)
        elif mnem == 'ADRP':
            op_1 = idc.get_operand_value(ea, 0)
            op_2 = idc.get_operand_value(ea, 1)
            off_reg = op_1
            off_data = op_2
        elif mnem == 'ADD':
            op_1 = idc.get_operand_value(ea, 0)
            op_2 = idc.get_operand_value(ea, 1)
            op_3 = idc.get_operand_value(ea, 2)
            op_3_type = idc.get_operand_type(ea, 2)
            if (op_1 == off_reg) and (op_2 == off_reg) and (op_3_type == idc.o_imm):
                off_data = off_data + op_3
                ldr_reg = off_reg - reg_base
                g_reg[ldr_reg] = off_data      
        elif (mnem == 'CSEL') or (mnem == 'CSINC') or (mnem == 'CSET') or (mnem == 'CINC'):
            ea = do_deobf(ea)
            continue
        ea = idc.next_head(ea)
 
 
def test():
    for i in range(len(g_reg)):
        print("%d:0x%x" % (i, g_reg[i]))
 
 
def main():
    ea = idc.get_screen_ea()
    func = idaapi.get_func(ea)
    ea = func.start_ea
    print("start deobf fun:0x%x" %(ea))
    deobf(ea)
    print("deobf ok!")
    pass
 
if __name__ == "__main__":
    main()
import idautils
import idc
import idaapi
import ida_ua
from keystone import *
 
g_reg = [0] * 40
reg_base = 129
g_cond_info = list()
ldr_reg = -1
add_reg = -1
 
ks = keystone.Ks(keystone.KS_ARCH_ARM64, keystone.KS_MODE_LITTLE_ENDIAN)
 
def get_opcode(ea):
    opcode = None
    disasm = idc.GetDisasm(ea)
    if disasm.find('LT') != -1:
        opcode = 'blt'
    elif disasm.find('EQ') != -1:
        opcode = 'beq'
    elif disasm.find('CC') != -1:
        opcode = 'bcc'
    elif disasm.find('GT') != -1:
        opcode = 'bgt'
    elif disasm.find('NE') != -1:
        opcode = 'bne' 
    elif disasm.find('GE') != -1:
        opcode = 'bge' 
    elif disasm.find('HI') != -1:
        opcode = 'bhi' 
    return opcode
 
 
def do_patch(patch_1, patch_2, opcode, cond_jmp_addr, uncond_jmp_addr):
    print("patch_1=0x%x patch_1=0x%x opcode=%s cond_jmp_addr=0x%x uncond_jmp_addr=0x%x" % (patch_1, patch_2, opcode, cond_jmp_addr, uncond_jmp_addr))
 
    jump_offset = " ({:d})".format(cond_jmp_addr - patch_1)
    repair_opcode = opcode + jump_offset
    encoding, count = ks.asm(repair_opcode)
    idaapi.patch_byte(patch_1, encoding[0])
    idaapi.patch_byte(patch_1 + 1, encoding[1])
    idaapi.patch_byte(patch_1 + 2, encoding[2])
    idaapi.patch_byte(patch_1 + 3, encoding[3])
 
    jump_offset = " ({:d})".format(uncond_jmp_addr - patch_2)
    repair_opcode = 'b' + jump_offset
    encoding, count = ks.asm(repair_opcode)
    idaapi.patch_byte(patch_2, encoding[0])
    idaapi.patch_byte(patch_2 + 1, encoding[1])
    idaapi.patch_byte(patch_2 + 2, encoding[2])
    idaapi.patch_byte(patch_2 + 3, encoding[3])
 
 
def do_deobf(ea):
    # 获取跳转条件
    opcode = get_opcode(ea)
    if opcode is None:
        print("opcode:unknown opcode 0x%x" % ea)
        return ea
 
    # 获取跳转信息
    cond_reg = -1
    uncond_reg = -1
    cond_data = -1
    uncond_data = -1
    mnem = idc.ida_ua.ua_mnem(ea)
    if mnem == 'CSEL':
        cond_reg = idc.get_operand_value(ea, 1)
        uncond_reg = idc.get_operand_value(ea, 2)
    elif mnem == 'CSET':
        cond_data = 1
        uncond_data = 0
    ea = idc.next_head(ea)
 
    # 获取LDR寄存器
    ldr_reg = -1
    lsl_value = -1
    mnem = idc.ida_ua.ua_mnem(ea)
    if mnem == 'LSL':
        lsl_value = idc.get_operand_value(ea, 2)
        ea = idc.next_head(ea)
        mnem = idc.ida_ua.ua_mnem(ea)
 
    if mnem != 'LDR':
        print("LDR:0x%x -> %s" % (ea, mnem))
        return ea
 
    operand_type = idc.get_operand_type(ea, 1)
    if operand_type == idc.o_phrase:
        insn = ida_ua.insn_t()
        ida_ua.decode_insn(insn, ea)
        ldr_reg = insn.Op2.reg
        if lsl_value == -1:
            lsl_value = insn.Op2.value
    else:
        return ea
    ea = idc.next_head(ea)
 
    # 获取ADD寄存器
    mnem = idc.ida_ua.ua_mnem(ea)
    if mnem == 'MOV':
        ea = idc.next_head(ea)
        mnem = idc.ida_ua.ua_mnem(ea)
 
    if mnem != 'ADD':
        print("ADD:0x%x -> %s" % (ea, mnem))
        return ea
    op_3 = idc.print_operand(ea, 2)
    op_3 = op_3[1:]
    ea = idc.next_head(ea)
 
    # 进行patch
    mnem = idc.ida_ua.ua_mnem(ea)
    if mnem != 'BR':
        print("BR:0x%x -> %s" % (ea, mnem))
        return ea
 
    #print('1 = %d 2 = %d 3 = 0x%x' % (g_reg[ldr_reg - reg_base],  g_reg[cond_reg - reg_base], g_reg[int(op_3)]))
    if cond_data != -1 and uncond_data != -1:
        print(lsl_value)
        cond_jmp_addr  = (idc.get_qword(g_reg[ldr_reg - reg_base] + (cond_data << lsl_value)) + g_reg[int(op_3)]) & 0xffffffffffffffff
        uncond_jmp_addr = (idc.get_qword(g_reg[ldr_reg - reg_base] + (uncond_data << lsl_value)) + g_reg[int(op_3)]) & 0xffffffffffffffff
    else:
        cond_jmp_addr   = (idc.get_qword(g_reg[ldr_reg - reg_base] + (g_reg[cond_reg - reg_base] << lsl_value)) + g_reg[int(op_3)]) & 0xffffffffffffffff
        uncond_jmp_addr = (idc.get_qword(g_reg[ldr_reg - reg_base] + (g_reg[uncond_reg - reg_base] << lsl_value)) + g_reg[int(op_3)]) & 0xffffffffffffffff
    do_patch(idc.prev_head(ea), ea, opcode, cond_jmp_addr, uncond_jmp_addr)
    return ea
 
 
def deobf(ea):
    off_reg = -1
    off_data = -1
    while True:
        mnem = idc.ida_ua.ua_mnem(ea)
        if mnem == 'RET':
            break
        elif mnem == 'MOV':
            op_1_type = idc.get_operand_type(ea, 0)
            op_2_type = idc.get_operand_type(ea, 1)
            if (op_1_type == idc.o_reg) and (op_2_type == idc.o_imm):
                op_1 = idc.get_operand_value(ea, 0)
                op_2 = idc.get_operand_value(ea, 1)
                g_reg[op_1 - reg_base] = op_2
        elif mnem == 'MOVK':
            op_1_type = idc.get_operand_type(ea, 0)
            op_2_type = idc.get_operand_type(ea, 1)
            op_3_type = idc.get_operand_type(ea, 2)
            if (op_1_type == idc.o_reg) and (op_2_type == idc.o_imm):
                op_1 = idc.get_operand_value(ea, 0)
                op_2 = idc.get_operand_value(ea, 1)
                g_reg[op_1 - reg_base] = (op_2 << 16) | (g_reg[op_1 - reg_base] & 0xffff)
        elif mnem == 'ADRP':
            op_1 = idc.get_operand_value(ea, 0)
            op_2 = idc.get_operand_value(ea, 1)
            off_reg = op_1
            off_data = op_2
        elif mnem == 'ADD':
            op_1 = idc.get_operand_value(ea, 0)
            op_2 = idc.get_operand_value(ea, 1)
            op_3 = idc.get_operand_value(ea, 2)
            op_3_type = idc.get_operand_type(ea, 2)
            if (op_1 == off_reg) and (op_2 == off_reg) and (op_3_type == idc.o_imm):
                off_data = off_data + op_3
                ldr_reg = off_reg - reg_base
                g_reg[ldr_reg] = off_data      
        elif (mnem == 'CSEL') or (mnem == 'CSINC') or (mnem == 'CSET') or (mnem == 'CINC'):
            ea = do_deobf(ea)
            continue
        ea = idc.next_head(ea)
 
 
def test():
    for i in range(len(g_reg)):
        print("%d:0x%x" % (i, g_reg[i]))
 
 
def main():
    ea = idc.get_screen_ea()
    func = idaapi.get_func(ea)
    ea = func.start_ea
    print("start deobf fun:0x%x" %(ea))
    deobf(ea)
    print("deobf ok!")
    pass
 
if __name__ == "__main__":
    main()
import idautils
import idc
import idaapi
 
 
decrypt_fun_list = dict()
 
def get_code_refs_to_list(addr):
    result = list(idautils.CodeRefsTo(addr, True))
    return result
 
 
def do_decrypt(src_addr, dst_addr, offset, eor_data, add_data, call_addr):
    flag = idc.get_wide_byte(src_addr)
    str_len = flag ^ (idc.get_wide_byte(src_addr + 1))
    final_str = ''
 
    for i in range(str_len):
        v4 = idc.get_wide_byte(src_addr + 2 + i)
        v5 = (flag + i) ^ eor_data
        final_str += chr((v4 ^ flag) & 0xff)
        flag = v5 + add_data
 
    decrypt_fun_list[call_addr] = final_str + "  " + str(hex(offset))
    print('decrypt_addr=0x%x offset=0x%x, final_str=%s' % (call_addr, offset, final_str))
 
 
def decrpt_str():
    decrypt_fun_list.clear()
    tmp_list = [7, 6, 5, 4, 3, 2, 1]
 
    fun_list = get_code_refs_to_list(0x106C54)
    if not fun_list:
        return
 
    for i in range(len(fun_list)):
        call_addr = fun_list[i]
        call_addr_start = idc.get_func_attr(call_addr, idc.FUNCATTR_START)
        caller_fun_list = get_code_refs_to_list(call_addr_start)
 
        for j in range(len(caller_fun_list)):
            call_decryptStr_addr = caller_fun_list[j]
            arg_addr = idc.prev_head(call_decryptStr_addr)
 
            mnem = idc.ida_ua.ua_mnem(arg_addr)
            register = idc.get_operand_value(arg_addr, 0)
            while True:
                if (register == 129) and (mnem == 'MOV'):
                    break
                arg_addr = idc.prev_head(arg_addr)
                mnem = idc.ida_ua.ua_mnem(arg_addr)
                register = idc.get_operand_value(arg_addr, 0)    
 
            offset = idc.get_operand_value(arg_addr, 1)
            if offset == 0xa0:
                offset = 0
            src_addr = 0x1250D8 + offset
            dst_addr = 0x15E778 + offset
 
            index = offset % 100
            eor_data = index
            add_data = tmp_list[(index % 7)]
 
            do_decrypt(src_addr, dst_addr, offset, eor_data, add_data, call_decryptStr_addr)
    pass
 
def main():
    decrpt_str()
 
if __name__ == "__main__":
    main()
import idautils
import idc
import idaapi
 
 
decrypt_fun_list = dict()
 
def get_code_refs_to_list(addr):
    result = list(idautils.CodeRefsTo(addr, True))
    return result
 
 
def do_decrypt(src_addr, dst_addr, offset, eor_data, add_data, call_addr):
    flag = idc.get_wide_byte(src_addr)
    str_len = flag ^ (idc.get_wide_byte(src_addr + 1))
    final_str = ''
 
    for i in range(str_len):
        v4 = idc.get_wide_byte(src_addr + 2 + i)
        v5 = (flag + i) ^ eor_data
        final_str += chr((v4 ^ flag) & 0xff)
        flag = v5 + add_data
 
    decrypt_fun_list[call_addr] = final_str + "  " + str(hex(offset))
    print('decrypt_addr=0x%x offset=0x%x, final_str=%s' % (call_addr, offset, final_str))
 
 
def decrpt_str():
    decrypt_fun_list.clear()
    tmp_list = [7, 6, 5, 4, 3, 2, 1]
 
    fun_list = get_code_refs_to_list(0x106C54)
    if not fun_list:
        return
 
    for i in range(len(fun_list)):
        call_addr = fun_list[i]
        call_addr_start = idc.get_func_attr(call_addr, idc.FUNCATTR_START)
        caller_fun_list = get_code_refs_to_list(call_addr_start)
 
        for j in range(len(caller_fun_list)):
            call_decryptStr_addr = caller_fun_list[j]
            arg_addr = idc.prev_head(call_decryptStr_addr)
 
            mnem = idc.ida_ua.ua_mnem(arg_addr)
            register = idc.get_operand_value(arg_addr, 0)
            while True:
                if (register == 129) and (mnem == 'MOV'):
                    break
                arg_addr = idc.prev_head(arg_addr)
                mnem = idc.ida_ua.ua_mnem(arg_addr)
                register = idc.get_operand_value(arg_addr, 0)    
 
            offset = idc.get_operand_value(arg_addr, 1)
            if offset == 0xa0:
                offset = 0
            src_addr = 0x1250D8 + offset
            dst_addr = 0x15E778 + offset
 
            index = offset % 100
            eor_data = index
            add_data = tmp_list[(index % 7)]
 
            do_decrypt(src_addr, dst_addr, offset, eor_data, add_data, call_decryptStr_addr)
    pass
 
def main():
    decrpt_str()
 
if __name__ == "__main__":
    main()
__loader_dlopen
__loader_android_dlopen_ext
rtld_db_dlactivity          //在非调试模式下为空函数,如果程序被调试则会被修改为对应的断点指令
__loader_dlopen
__loader_android_dlopen_ext
rtld_db_dlactivity          //在非调试模式下为空函数,如果程序被调试则会被修改为对应的断点指令
cc/binmt/signature/PmsHookApplication
com/cloudinject/feature/App
np/manager/FuckSign
bin/mt/apksignaturekillerplus/HookApplication
cc/binmt/signature/PmsHookApplication
com/cloudinject/feature/App
np/manager/FuckSign
bin/mt/apksignaturekillerplus/HookApplication
/init.vbox86.rc
/dev/socket/genyd
/data/data/com.tencent.tinput
init.android_x86.rc
ueventd.android_x86.rc
/system/framework/x86
/init.vbox86.rc
/dev/socket/genyd
/data/data/com.tencent.tinput
init.android_x86.rc
ueventd.android_x86.rc
/system/framework/x86
import idautils
import idc
import idaapi
 
decrypt_fun_list = dict()
 
def get_code_refs_to_list(addr):
    result = list(idautils.CodeRefsTo(addr, True))
    return result
 
def do_decrypt(src_addr, dst_addr, offset, eor_data, add_data, call_addr):
    flag = idc.get_wide_byte(src_addr)
    str_len = flag ^ (idc.get_wide_byte(src_addr + 1))
    final_str = ''
 
    for i in range(str_len):
        v10 = idc.get_wide_byte(src_addr + 2 + i) ^ flag
        flag = ((i + flag) ^ eor_data) + add_data
        final_str += chr(v10 & 0xff)
 
    decrypt_fun_list[call_addr] = final_str + "  " + str(hex(offset))
    print('call_addr=0x%x, offset=0x%x, eor_data=0x%x, add_data=0x%x, final_str=%s' % (call_addr, offset, eor_data, add_data, final_str))
 
def decrpt_str():
    decrypt_fun_list.clear()
    tmp_list = [7, 6, 5, 4, 3, 2, 1]
    fun_list = get_code_refs_to_list(0x27E724)
    if not fun_list:
        return
 
    for i in range(len(fun_list)):
        arg_addr = fun_list[i]
        call_addr = arg_addr
        fun_start = idc.get_func_attr(arg_addr, idc.FUNCATTR_START)
 
        mnem = idc.ida_ua.ua_mnem(arg_addr)
        register = idc.get_operand_value(arg_addr, 0)
        while arg_addr >= fun_start:
            if (register == 129) and (mnem == 'MOV'):
                offset = idc.get_operand_value(arg_addr, 1)
                break
            arg_addr = idc.prev_head(arg_addr)
            mnem = idc.ida_ua.ua_mnem(arg_addr)
            register = idc.get_operand_value(arg_addr, 0)
 
        if offset == 0xa0:
            offset = 0
        index = offset % 100
 
        eor_data = index
        add_data = tmp_list[(index % 7)]
 
        # src = 0x3880E4 dst = 0x4C9B78
        src_addr = 0x3880E4 + offset
        dst_addr = 0x4C9B78 + offset
        do_decrypt(src_addr, dst_addr, offset, eor_data, add_data, call_addr)
 
def main():
    decrpt_str()
 
if __name__ == "__main__":
    main()
import idautils
import idc
import idaapi
 
decrypt_fun_list = dict()
 
def get_code_refs_to_list(addr):
    result = list(idautils.CodeRefsTo(addr, True))
    return result
 
def do_decrypt(src_addr, dst_addr, offset, eor_data, add_data, call_addr):
    flag = idc.get_wide_byte(src_addr)
    str_len = flag ^ (idc.get_wide_byte(src_addr + 1))
    final_str = ''
 
    for i in range(str_len):
        v10 = idc.get_wide_byte(src_addr + 2 + i) ^ flag
        flag = ((i + flag) ^ eor_data) + add_data
        final_str += chr(v10 & 0xff)
 
    decrypt_fun_list[call_addr] = final_str + "  " + str(hex(offset))
    print('call_addr=0x%x, offset=0x%x, eor_data=0x%x, add_data=0x%x, final_str=%s' % (call_addr, offset, eor_data, add_data, final_str))
 
def decrpt_str():
    decrypt_fun_list.clear()
    tmp_list = [7, 6, 5, 4, 3, 2, 1]
    fun_list = get_code_refs_to_list(0x27E724)
    if not fun_list:
        return
 
    for i in range(len(fun_list)):
        arg_addr = fun_list[i]
        call_addr = arg_addr
        fun_start = idc.get_func_attr(arg_addr, idc.FUNCATTR_START)
 
        mnem = idc.ida_ua.ua_mnem(arg_addr)
        register = idc.get_operand_value(arg_addr, 0)
        while arg_addr >= fun_start:
            if (register == 129) and (mnem == 'MOV'):
                offset = idc.get_operand_value(arg_addr, 1)
                break
            arg_addr = idc.prev_head(arg_addr)
            mnem = idc.ida_ua.ua_mnem(arg_addr)
            register = idc.get_operand_value(arg_addr, 0)
 
        if offset == 0xa0:
            offset = 0
        index = offset % 100
 
        eor_data = index
        add_data = tmp_list[(index % 7)]
 
        # src = 0x3880E4 dst = 0x4C9B78
        src_addr = 0x3880E4 + offset
        dst_addr = 0x4C9B78 + offset
        do_decrypt(src_addr, dst_addr, offset, eor_data, add_data, call_addr)
 
def main():
    decrpt_str()
 
if __name__ == "__main__":
    main()
__int64 __fastcall sub_26A218(__int64 result)
{
  v1 = result;
  if ( !*(_QWORD *)(result + 8) )
  {
    v11 = sub_27E724(0x1ADE);
    v12 = 0;
    v13[0] = (__int64)sub_26E5D8;
    v13[1] = sub_27E724(0x1AEB);
    v14 = 0;
    v15 = sub_26E644;
    v16 = sub_27E724(0x1AF9);
    v17 = 0;
    v18 = sub_26E700;
    v19 = sub_27E724(0x147E);
    v20 = 13;
    v21 = sub_26B698;
    v22 = sub_27E724(5260);
    v23 = 11;
    v24 = sub_26B398;
    v25 = sub_27E724(5266);
    v26 = 4;
    v27 = sub_26B714;
    v28 = sub_27E724(5276);
    v29 = 4;
    v30 = sub_26B748;
    v31 = sub_27E724(5286);
    v32 = 2;
    v33 = sub_26B76C;
    v34 = sub_27E724(5299);
    v35 = 3;
    v36 = sub_26B79C;
    v37 = sub_27E724(5312);
    v38 = 3;
    v39 = &sub_26B824;
    v40 = sub_27E724(5322);
    v41 = 14;
    v42 = sub_26CC04;
    v43 = sub_27E724(5330);
    v44 = 3;
    v45 = &sub_26B8A0;
    v46 = sub_27E724(5341);
    v47 = 3;
    v48 = sub_26B918;
    v49 = sub_27E724(5356);
    v50 = 5;
    v51 = sub_26BB7C;
    v52 = sub_27E724(5370);
    v53 = 3;
    v54 = sub_26BACC;
    v55 = sub_27E724(5384);
    v56 = 4;
    v57 = sub_26BD10;
    v58 = sub_27E724(5398);
    v59 = 4;
    v60 = sub_26BDE8;
    v61 = sub_27E724(5413);
    v62 = 5;
    v63 = sub_26BEBC;
    v64 = sub_27E724(5428);
    v65 = 5;
    v66 = sub_26BF74;
    v67 = sub_27E724(5443);
    v68 = 5;
    v69 = sub_26C02C;
    v70 = sub_27E724(5458);
    v71 = 2;
    v72 = sub_26C0E4;
    v73 = sub_27E724(5465);
    v74 = 3;
    v75 = sub_26C128;
    v76 = sub_27E724(5478);
    v77 = 3;
    v78 = sub_26C208;
    v79 = sub_27E724(5491);
    v80 = 3;
    v81 = sub_26C1C8;
    v82 = sub_27E724(5504);
    v83 = 3;
    v84 = sub_26C248;
    v85 = sub_27E724(5521);
    v86 = 3;
    v87 = sub_26C288;
    v88 = sub_27E724(5539);
    v89 = 3;
    v90 = sub_26C338;
    v91 = sub_27E724(5553);
    v92 = 3;
    v93 = sub_26C3AC;
    v94 = sub_27E724(5566);
    v95 = 3;
    v96 = sub_26C45C;
    v97 = sub_27E724(5579);
    v98 = 3;
    v99 = sub_26C404;
    v100 = sub_27E724(5592);
    v101 = 3;
    v102 = sub_26B934;
    v103 = sub_27E724(5605);
    v104 = 3;
    v105 = sub_26B9BC;
    v106 = sub_27E724(5618);
    v107 = 3;
    v108 = sub_26BA44;
    v109 = sub_27E724(5631);
    v110 = 17;
    v111 = sub_26CC54;
    v112 = sub_27E724(5645);
    v113 = 18;
    v114 = sub_26CC98;
    v115 = sub_27E724(5661);
    v116 = 19;
    v117 = sub_26CCF4;
    v118 = sub_27E724(5681);
    v119 = 15;
    v120 = sub_26C4B4;
    v121 = sub_27E724(5700);
    v122 = 20;
    v123 = sub_26CD64;
    v124 = sub_27E724(5713);
    v125 = 3;
    v126 = sub_26CE88;
    v127 = sub_27E724(5730);
    v128 = 3;
    v129 = sub_26CF3C;
    v130 = sub_27E724(0x1678);
    v131 = 3;
    v132 = sub_26CFF0;
    v133 = sub_27E724(5768);
    v134 = 6;
    v135 = sub_26D08C;
    v136 = sub_27E724(5780);
    v137 = 6;
    v138 = sub_26D1C8;
    v139 = sub_27E724(5796);
    v140 = 7;
    v141 = sub_26D334;
    v142 = sub_27E724(5809);
    v143 = 7;
    v144 = sub_26D33C;
    v145 = sub_27E724(6915);
    v146 = 2;
    v147 = sub_26D344;
    v148 = sub_27E724(5826);
    v149 = 2;
    v150 = sub_26D3B8;
    v151 = sub_27E724(5840);
    v152 = 2;
    v153 = sub_26D3E8;
    v154 = sub_27E724(5858);
    v155 = 1;
    v156 = sub_26DA50;
    v157 = sub_27E724(5870);
    v158 = 1;
    v159 = sub_26DA5C;
    v160 = sub_27E724(5882);
    v161 = 7;
    v162 = sub_26DC8C;
    v163 = sub_27E724(5897);
    v164 = 7;
    v165 = sub_26DC94;
    v166 = sub_27E724(5916);
    v167 = 3;
    v168 = sub_26DC9C;
    v169 = sub_27E724(6460);
    v170 = 3;
    v171 = sub_26DCB8;
    v172 = sub_27E724(6669);
    v173 = 1;
    v174 = sub_26C598;
    v175 = sub_27E724(5934);
    v176 = 15;
    v177 = sub_26C5C4;
    v178 = sub_27E724(5949);
    v179 = 7;
    v180 = sub_26E1B0;
    v181 = sub_27E724(5974);
    v182 = 7;
    v183 = sub_26E1B8;
    v184 = sub_27E724(6003);
    v185 = 1;
    v186 = sub_26C5B4;
    v187 = sub_27E724(6012);
    v188 = 1;
    v189 = sub_26C5BC;
    v190 = sub_27E724(6021);
    v191 = 15;
    v192 = sub_26C5DC;
    v193 = sub_27E724(6032);
    v194 = 15;
    v195 = sub_26C660;
    v196 = sub_27E724(6042);
    v197 = 14;
    v198 = sub_26C6E4;
    v199 = sub_27E724(6058);
    v200 = 3;
    v201 = sub_26C780;
    v202 = sub_27E724(6388);
    v203 = 3;
    v204 = sub_26C7D4;
    v205 = sub_27E724(6074);
    v206 = 15;
    v207 = sub_26D418;
    v208 = sub_27E724(6085);
    v209 = 5;
    v210 = sub_26D5AC;
    v211 = sub_27E724(6098);
    v212 = 5;
    v213 = sub_26D5EC;
    v214 = sub_27E724(6115);
    v215 = 5;
    v216 = sub_26D62C;
    v217 = sub_27E724(6129);
    v218 = 5;
    v219 = sub_26D704;
    v220 = sub_27E724(6143);
    v221 = 5;
    v222 = sub_26D6C0;
    v223 = sub_27E724(6157);
    v224 = 3;
    v225 = sub_26D748;
    v226 = sub_27E724(6175);
    v227 = 5;
    v228 = sub_26D870;
    v229 = sub_27E724(6194);
    v230 = 5;
    v231 = sub_26D8B0;
    v232 = sub_27E724(6368);
    v233 = 1;
    v234 = sub_26E1C0;
    v235 = sub_27E724(6378);
    v236 = 2;
    v237 = &sub_26E1D8;
    v238 = sub_27E724(6482);
    v239 = 1;
    v240 = sub_26DE88;
    v241 = sub_27E724(6506);
    v242 = 3;
    v243 = sub_26E264;
    v244 = sub_27E724(6533);
    v245 = 2;
    v246 = &sub_26E360;
    v247 = sub_27E724(6561);
    v248 = 2;
    v249 = &sub_26E3C8;
    v250 = sub_27E724(6590);
    v251 = 1;
    v252 = sub_26E430;
    v253 = sub_27E724(6604);
    v254 = 1;
    v255 = sub_26E438;
    v256 = sub_27E724(6628);
    v257 = 1;
    v258 = sub_26E450;
    v259 = sub_27E724(6647);
    v260 = 2;
    v261 = sub_26E46C;
    v262 = sub_27E724(6783);
    v263 = 1;
    v264 = sub_26E538;
    v265 = sub_27E724(6802);
    v266 = 3;
    v267 = &sub_26E540;
    v268 = sub_27E724(6823);
    v269 = 1;
    v270 = sub_26E5BC;
    v271 = sub_27E724(6274);
    v272 = 5;
    v273 = sub_26C828;
    v274 = sub_27E724(6292);
    v275 = 1;
    v276 = sub_26C8C4;
    v277 = sub_27E724(6302);
    v278 = 1;
    v279 = sub_26C8E0;
    v280 = sub_27E724(6312);
    v281 = 3;
    v282 = sub_26C8FC;
    v283 = sub_27E724(6326);
    v284 = 3;
    v285 = sub_26C97C;
    v286 = sub_27E724(6340);
    v287 = 4;
    v288 = sub_26CA00;
    v289 = sub_27E724(6929);
    v290 = 3;
    v291 = sub_26CA44;
    v292 = sub_27E724(6939);
    v293 = 3;
    v294 = sub_26CAC4;
    v295 = sub_27E724(6949);
    v296 = 4;
    v297 = sub_26CB48;
    v298 = sub_27E724(6357);
    v299 = 2;
    v300 = &sub_26CB90;
    v301 = sub_27E724(6405);
    v302 = 3;
    v303 = sub_26DD1C;
    v304 = sub_27E724(6428);
    v305 = 3;
    v306 = sub_26DD7C;
    v307 = sub_27E724(6442);
    v308 = 3;
    v309 = sub_26DE00;
    v310 = sub_27E724(6695);
    v311 = 1;
    v312 = sub_26DE08;
    v313 = sub_27E724(6714);
    v314 = 1;
    v315 = sub_26DE38;
    v316 = sub_27E724(6733);
    v317 = 1;
    v318 = sub_26DE68;
    v319 = sub_27E724(6766);
    v320 = 1;
    v321 = sub_26DE84;
    v322 = sub_27E724(6836);
    v323 = 3;
    v324 = &sub_26DF54;
    v325 = sub_27E724(6851);
    v326 = 4;
    v327 = &sub_26DFBC;
    v328 = sub_27E724(6962);
    v329 = 14;
    v330 = sub_26E044;
    v331 = sub_27E724(6978);
    v332 = 5;
    v2 = 0LL;
    v333 = sub_26E058;
    do
    {
      v3 = *(unsigned __int8 **)((char *)&v11 + v2 * 8);
      v4 = strlen_sub_2398FC((__int64)v3);
      v5 = crc32_sub_22B670(v3, v4);
      v6 = v13[v2];
      v7 = *(_OWORD *)((char *)&v11 + v2 * 8);
      v8 = v5;
      v10 = v6;
      v9 = v7;
      result = sub_26B030(v1, &v8);
      v2 += 3LL;
    }
    while ( v2 != 324 );
  }
  return result;
}
__int64 __fastcall sub_26A218(__int64 result)
{
  v1 = result;
  if ( !*(_QWORD *)(result + 8) )
  {
    v11 = sub_27E724(0x1ADE);
    v12 = 0;
    v13[0] = (__int64)sub_26E5D8;
    v13[1] = sub_27E724(0x1AEB);
    v14 = 0;
    v15 = sub_26E644;
    v16 = sub_27E724(0x1AF9);
    v17 = 0;
    v18 = sub_26E700;
    v19 = sub_27E724(0x147E);
    v20 = 13;
    v21 = sub_26B698;
    v22 = sub_27E724(5260);
    v23 = 11;
    v24 = sub_26B398;
    v25 = sub_27E724(5266);
    v26 = 4;
    v27 = sub_26B714;
    v28 = sub_27E724(5276);
    v29 = 4;
    v30 = sub_26B748;
    v31 = sub_27E724(5286);
    v32 = 2;
    v33 = sub_26B76C;
    v34 = sub_27E724(5299);
    v35 = 3;
    v36 = sub_26B79C;
    v37 = sub_27E724(5312);
    v38 = 3;
    v39 = &sub_26B824;
    v40 = sub_27E724(5322);
    v41 = 14;
    v42 = sub_26CC04;
    v43 = sub_27E724(5330);
    v44 = 3;
    v45 = &sub_26B8A0;
    v46 = sub_27E724(5341);
    v47 = 3;
    v48 = sub_26B918;
    v49 = sub_27E724(5356);
    v50 = 5;
    v51 = sub_26BB7C;
    v52 = sub_27E724(5370);
    v53 = 3;
    v54 = sub_26BACC;
    v55 = sub_27E724(5384);
    v56 = 4;
    v57 = sub_26BD10;
    v58 = sub_27E724(5398);
    v59 = 4;
    v60 = sub_26BDE8;
    v61 = sub_27E724(5413);
    v62 = 5;
    v63 = sub_26BEBC;
    v64 = sub_27E724(5428);
    v65 = 5;
    v66 = sub_26BF74;
    v67 = sub_27E724(5443);
    v68 = 5;
    v69 = sub_26C02C;
    v70 = sub_27E724(5458);
    v71 = 2;
    v72 = sub_26C0E4;
    v73 = sub_27E724(5465);
    v74 = 3;
    v75 = sub_26C128;
    v76 = sub_27E724(5478);
    v77 = 3;
    v78 = sub_26C208;
    v79 = sub_27E724(5491);
    v80 = 3;
    v81 = sub_26C1C8;

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

最后于 2023-5-31 09:37 被2beNo2编辑 ,原因: 补充内容
收藏
免费 20
支持
分享
打赏 + 15.00雪花
打赏次数 2 雪花 + 15.00
 
赞赏  wuxin159   +10.00 2023/08/14
赞赏  orz1ruo   +5.00 2023/06/09 原创内容~
最新回复 (31)
雪    币: 226
活跃值: (2308)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
tql
2023-5-31 09:00
0
雪    币: 3004
活跃值: (30866)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2023-5-31 09:26
1
雪    币: 129
活跃值: (4490)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
听闻一个大佬,这两个东西可以关闭的
2023-5-31 09:53
0
雪    币: 5916
活跃值: (4810)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
大佬,能否给个so或者APP的链接?版本号?
2023-5-31 11:17
0
雪    币: 3493
活跃值: (4774)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
6
mb_rjdrqvpa 大佬,能否给个so或者APP的链接?版本号?
https://sr.mihoyo.com/   官网直接下载,我这边版本是1.0.5
2023-5-31 11:22
0
雪    币: 1671
活跃值: (215822)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
7
tql
2023-5-31 13:08
0
雪    币: 5916
活跃值: (4810)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
2beNo2 https://sr.mihoyo.com/ 官网直接下载,我这边版本是1.0.5
感谢大佬
2023-5-31 15:36
1
雪    币: 541
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9
tql
2023-5-31 17:34
0
雪    币: 2325
活跃值: (2304)
能力值: ( LV6,RANK:89 )
在线值:
发帖
回帖
粉丝
10
牛逼 这都不是精华?版主呢
2023-5-31 17:38
0
雪    币: 47
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
11
我看不懂,但我大受震撼
2023-6-1 14:53
0
雪    币: 1110
活跃值: (3254)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
12
删前留名
2023-6-1 16:26
0
雪    币: 4870
活跃值: (18870)
能力值: ( LV13,RANK:317 )
在线值:
发帖
回帖
粉丝
13
感谢分享~
2023-6-1 16:32
0
雪    币: 3
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
14
太强了
2023-6-1 18:39
0
雪    币: 573
活跃值: (1009)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
16
玛卡巴卡
2023-6-7 10:55
0
雪    币: 3
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
17
大牛,怎么才能和你一样强,该学些啥呢,没方向,求指导一下
2023-6-18 02:19
1
雪    币: 12
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
18
方便留个联系?
2023-6-18 15:46
0
雪    币: 1422
活跃值: (1573)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
19
我敲, 爆锤tprt
2023-6-20 18:30
0
雪    币: 3493
活跃值: (4774)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
20
Mark. 大牛,怎么才能和你一样强,该学些啥呢,没方向,求指导一下
在科锐学习的,具体学习方向你可以参考科锐的课程表
2023-6-23 16:23
0
雪    币: 9
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
21
大佬,在方法sub_22B670对代码段做了crc校验  是怎么看出来的呀
2023-6-23 19:18
0
雪    币: 6
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
22
大佬可否录个视频,这图文有些地方好像不全
2023-7-3 11:13
0
雪    币: 3
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
23
2beNo2 在科锐学习的,具体学习方向你可以参考科锐的课程表
谢谢大牛指导
2023-7-4 20:51
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
24

大佬这debug检测真是头疼,求指点

2023-7-8 15:58
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
25

懵了

上传的附件:
2023-7-8 15:59
0
游客
登录 | 注册 方可回帖
返回
//