|
|
|
|
|
|
|
|
|
|
|
|
|
|
[原创]Python调用微信OCR识别文字和坐标
麻烦 用pybind11 几行代码 |
|
|
|
|
|
|
|
|
|
|
|
[求助]app360的壳,大佬闲着没事可脱一下
还修复?- - onCreate都native了 so vmp了 你这个价格真是让大家见笑了 |
|
|
[求助]app360的壳,大佬闲着没事可脱一下
package com.guugoo.jiapeiteacher.util;
import com.google.gson.JsonObject;
import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class EncryptUtils {
private static char[] alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".toCharArray();
private static byte[] codes = new byte[256];
public static JsonObject encryptDES(String str) {
JsonObject jsonObject = new JsonObject();
try {
Cipher instance = Cipher.getInstance("DES/CBC/PKCS5Padding");
instance.init(1, SecretKeyFactory.getInstance("DES").generateSecret(new DESKeySpec("nkgg8686".getBytes("UTF-8"))), new IvParameterSpec("nkgg8686".getBytes()));
jsonObject.addProperty("Parameter", new String(encode(instance.doFinal(str.getBytes("UTF-8")))));
} catch (Exception e) {
e.printStackTrace();
}
return jsonObject;
}
public static String decryptDES(String str) {
try {
IvParameterSpec ivParameterSpec = new IvParameterSpec("nkgg8686".getBytes());
SecretKeySpec secretKeySpec = new SecretKeySpec("nkgg8686".getBytes(), "DES");
Cipher instance = Cipher.getInstance("DES/CBC/PKCS5Padding");
instance.init(2, secretKeySpec, ivParameterSpec);
return new String(instance.doFinal(decode(str.toCharArray())));
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
public static String decryptDES3(String str) {
try {
IvParameterSpec ivParameterSpec = new IvParameterSpec("nkgg6666".getBytes());
SecretKeySpec secretKeySpec = new SecretKeySpec("nkgg6666".getBytes(), "DES");
Cipher instance = Cipher.getInstance("DES/CBC/PKCS5Padding");
instance.init(2, secretKeySpec, ivParameterSpec);
return new String(instance.doFinal(decode(str.toCharArray())));
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
public static String decryptDE1(String str) {
try {
IvParameterSpec ivParameterSpec = new IvParameterSpec("12345678".getBytes());
SecretKeySpec secretKeySpec = new SecretKeySpec("12345678".getBytes(), "DES");
Cipher instance = Cipher.getInstance("DES/CBC/PKCS5Padding");
instance.init(2, secretKeySpec, ivParameterSpec);
return new String(instance.doFinal(decode(str.toCharArray())));
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
public static char[] encode(byte[] bArr) {
boolean z;
char[] cArr = new char[(((bArr.length + 2) / 3) * 4)];
int i = 0;
int i2 = 0;
while (i < bArr.length) {
int i3 = (bArr[i] & 255) << 8;
int i4 = i + 1;
boolean z2 = true;
if (i4 < bArr.length) {
i3 |= bArr[i4] & 255;
z = true;
} else {
z = false;
}
int i5 = i3 << 8;
int i6 = i + 2;
if (i6 < bArr.length) {
i5 |= bArr[i6] & 255;
} else {
z2 = false;
}
int i7 = 64;
cArr[i2 + 3] = alphabet[z2 ? i5 & 63 : 64];
int i8 = i5 >> 6;
int i9 = i2 + 2;
char[] cArr2 = alphabet;
if (z) {
i7 = i8 & 63;
}
cArr[i9] = cArr2[i7];
int i10 = i8 >> 6;
char[] cArr3 = alphabet;
cArr[i2 + 1] = cArr3[i10 & 63];
cArr[i2 + 0] = cArr3[(i10 >> 6) & 63];
i += 3;
i2 += 4;
}
return cArr;
}
public static byte[] decode(char[] cArr) {
int length = ((cArr.length + 3) / 4) * 3;
if (cArr.length > 0 && cArr[cArr.length - 1] == '=') {
length--;
}
if (cArr.length > 1 && cArr[cArr.length - 2] == '=') {
length--;
}
byte[] bArr = new byte[length];
int i = 0;
int i2 = 0;
int i3 = 0;
for (char c : cArr) {
byte b = codes[c & 255];
if (b >= 0) {
i3 += 6;
i2 = (i2 << 6) | b;
if (i3 >= 8) {
i3 -= 8;
bArr[i] = (byte) ((i2 >> i3) & 255);
i++;
}
}
}
if (i == bArr.length) {
return bArr;
}
throw new Error("miscalculated data length!");
}
static {
for (int i = 0; i < 256; i++) {
codes[i] = -1;
}
for (int i2 = 65; i2 <= 90; i2++) {
codes[i2] = (byte) (i2 - 65);
}
for (int i3 = 97; i3 <= 122; i3++) {
codes[i3] = (byte) ((i3 + 26) - 97);
}
for (int i4 = 48; i4 <= 57; i4++) {
codes[i4] = (byte) ((i4 + 52) - 48);
}
byte[] bArr = codes;
bArr[43] = 62;
bArr[47] = 63;
}
} |
|
|
[原创]简单完善《ARM64 OLLVM反混淆》中的脚本
按自己的理解,抄了一遍,阅读性可能会好一点 import sys
import logging
import unicorn
import capstone
import keystone
logging.basicConfig(
stream=sys.stdout,
level=logging.DEBUG,
format="%(asctime)s %(levelname)7s %(name)s | %(message)s"
)
logger = logging.getLogger("ollvm")
class BlockItem:
start_addr: int = None
end_addr: int = None
jump_addr: int = None
ins_list: list = None
has_bl_ins: bool = False
has_ret_ins: bool = False
has_csel_ins: bool = False
_sign: str = None
@property
def sign(self):
'''
生成签名
:return:
'''
if self._sign is not None:
return self._sign
self._sign = ''
for ins in self.ins_list:
self._sign += ins.mnemonic
for op in ins.operands:
self._sign += str(op.type)
return self._sign
@property
def csel_ins(self) -> capstone.CsInsn:
if not self.has_csel_ins:
return None
for ins in self.ins_list:
if ins.id == capstone.arm64.ARM64_INS_CSEL:
return ins
return None
@property
def last_ins(self) -> capstone.CsInsn:
return self.ins_list[-1]
class FuncContext():
real_blocks: list = None
func_start_addr: int = 0
func_end_addr: int = 0
trace_list: list = None
block_map: dict = None
is_success: bool = False
start_addr: int = 0
dist_addr: int = 0
branch_control:int = 1
def UR(regname):
'''
将寄存器名称转unicorn 寄存器id
如: 'x1' => UC_ARM64_REG_X1
:param regname:
:return:
'''
return getattr(unicorn.arm64_const, 'UC_ARM64_REG_{0}'.format(regname.upper()), None)
class FuckArm64Ollvm:
_END_GROUPS = [capstone.arm64.ARM64_GRP_RET, capstone.arm64.ARM64_GRP_BRANCH_RELATIVE, capstone.arm64.ARM64_GRP_JUMP]
_FAKE_BLOCK_SINGS = [
'movz12movk12b2',
'cmp11mov11b.ne2',
'movz12movk12cmp11b.eq2',
'movz12movk12cmp11mov11b.ne2',
'movz12movk12cmp11movz12movk12b.eq2',
]
_MU_SKIP_INS = ['bl']
def __init__(self, so_path: str):
self.so_path = so_path
self.so_bin = self._open_so(so_path)
self.capstone = self._get_capstone()
self.mu: unicorn.Uc = None
self.ks = self._get_ks()
def _open_so(self, so_path: str) -> bytes:
with open(so_path, 'rb') as fp:
return fp.read()
def _mu_hook_code(self, mu: unicorn.Uc, address, size, user_data: FuncContext):
if user_data.is_success:
mu.emu_stop()
return
if address > user_data.func_end_addr:
mu.emu_stop()
return
#一个真实块应该只会被执行一次, 否则说明可能把虚假块当成真实块了
if address in user_data.real_blocks:
if address in user_data.trace_list:
print("This maybe a fake block. codesign:%s " % user_data.block_map[address].sign)
mu.emu_stop()
return
else:
user_data.trace_list.append(address)
#寻找到下一个真实块时
if address in user_data.real_blocks and address != user_data.start_addr:
user_data.is_success = True
user_data.dist_addr = address
logger.info("find dist addr: 0x%x" % address)
mu.emu_stop()
return
code_bin = self.so_bin[address:address+size]
try:
ins = next(self.capstone.disasm(code_bin, address))
except StopIteration:
mu.emu_stop()
return
#ret指令
if ins.mnemonic == 'ret':
mu.reg_write(unicorn.arm64_const.UC_ARM64_REG_PC, 0)
mu.emu_stop()
logger.info("ret ins..")
return
# 跳过函数调用和非栈空间内存访问
is_skip = False
for bl in self._MU_SKIP_INS:
if bl in ins.mnemonic:
is_skip = True
break
if '[' in ins.op_str and 'sp' in ins.op_str:
addr = self._get_ins_mem_addr(mu, ins)
if addr < 0x80000000 and addr >= 0x80000000 + 0x10000 * 8:
is_skip = True
if is_skip:
logger.info("will pass 0x%x:\t%s\t%s" %(ins.address, ins.mnemonic, ins.op_str))
mu.reg_write(unicorn.arm64_const.UC_ARM64_REG_PC, address + size)
return
# 人工交换csel指令的值来实现分支
if ins.mnemonic == 'csel':
reg_list = self._get_uc_reg_list(ins)
reg1_val = mu.reg_read(reg_list[1])
reg2_val = mu.reg_read(reg_list[2])
if user_data.branch_control == 1:
mu.reg_write(reg_list[0], reg1_val)
else:
mu.reg_write(reg_list[0], reg2_val)
mu.reg_write(unicorn.arm64_const.UC_ARM64_REG_PC, address + size)
def _get_uc_reg_list(self, ins: capstone.CsInsn):
'''
将capstone指令中的所有寄存器转unicore寄存器id
:param ins:
:return:
'''
regid_list = []
for op in ins.operands:
if op.type == capstone.arm64.ARM64_OP_REG:
regid_list.append(UR(ins.reg_name(op.reg)))
return regid_list
def _get_ins_mem_addr(self, mu, ins: capstone.CsInsn):
'''
计算指令操作的内存地址
如 STR X0, [X19,#0xB8]; X19是mem.base, 0xB8是mem.disp
如 STR X0, [X2,X4]; X2是mem.base, x4是op.mem.index
:param mu:
:param ins:
:return:
'''
addr = 0
for op in ins.operands:
if op.type == capstone.arm64.ARM64_OP_MEM:
if op.mem.base != 0:
regname = ins.reg_name(op.mem.base)
uc_reg_id = UR(regname)
addr += mu.reg_read(uc_reg_id)
elif op.mem.index != 0:
regname = ins.reg_name(op.mem.index)
uc_reg_id = UR(regname)
addr += mu.reg_read(uc_reg_id)
elif op.mem.disp != 0:
addr += op.mem.disp
return addr
def _mu_hook_mem_unmapped(self, mu, type, address, size, value, user_data: FuncContext):
pc = mu.reg_read(unicorn.arm64_const.UC_ARM64_REG_PC)
logger.error('mem_unmapped pc:%x type:%d addr:%x size:%x' % (pc, type, address, size))
return False
def _get_mu(self, user_data):
if self.mu is not None:
try:
self.mu.emu_stop()
except unicorn.UcError as e:
logger.error(e)
mu = unicorn.Uc(unicorn.UC_ARCH_ARM64, unicorn.UC_MODE_ARM)
mu.mem_map(0x80000000, 0x10000 * 8)
mu.mem_map(0, 4 * 1024 * 1024)
mu.mem_write(0, self.so_bin)
mu.reg_write(unicorn.arm64_const.UC_ARM64_REG_SP, 0x80000000 + 0x10000 * 6)
mu.hook_add(unicorn.UC_HOOK_CODE, self._mu_hook_code, user_data=user_data)
mu.hook_add(unicorn.UC_HOOK_MEM_UNMAPPED, self._mu_hook_mem_unmapped, user_data=user_data)
return mu
def _get_mu_context(self):
reg_vals = []
for i in range(31):
reg_vals.append(self.mu.reg_read(UR('x{0}'.format(i))))
reg_vals.append(self.mu.reg_read(UR('sp')))
return reg_vals
def _set_mu_context(self, reg_vals):
if reg_vals is None:
return
if len(reg_vals) != 32:
return
for i in range(31):
self.mu.reg_write(UR('x{0}'.format(i)), reg_vals[i])
self.mu.reg_write(UR('sp'), reg_vals[31])
def _get_capstone(self, detail=True):
md = capstone.Cs(capstone.CS_ARCH_ARM64, capstone.CS_MODE_ARM)
md.detail = detail
return md
def _get_ks(self):
return keystone.Ks(keystone.KS_ARCH_ARM64, keystone.KS_MODE_LITTLE_ENDIAN)
def _is_block_end(self, ins:capstone.CsInsn):
'''
判断指令是否为跳转或返回指令
:param ins_groups:
:return:
'''
ins_groups = ins.groups
if ins_groups is None:
return False
if len(ins_groups) == 0:
return False
for group in self._END_GROUPS:
if group in ins_groups:
return True
return False
def _is_bl(self, ins: capstone.CsInsn):
'''
是否为bl指令
:param ins:
:return:
'''
return ins.id == capstone.arm64.ARM64_INS_BL
def _is_ret(self, ins: capstone.CsInsn):
'''
是否为ret指令
:param ins:
:return:
'''
return ins.id == capstone.arm64.ARM64_INS_RET
def _is_csel(self, ins:capstone.CsInsn):
'''
是否为csel指令
:param ins:
:return:
'''
return ins.id == capstone.arm64.ARM64_INS_CSEL
def _get_ins_imm(self, ins: capstone.CsInsn):
'''
获取指令的立即数
:param ins:
:return:
'''
opr: capstone.arm64.Arm64Op = None
for opr in ins.operands:
if opr.type == capstone.arm64.ARM64_OP_IMM:
return opr.imm
return None
def _is_fake_block(self, block_item: BlockItem):
'''
根据预设特征判断是否为虚假块
:param block_item:
:return:
'''
if block_item.sign in self._FAKE_BLOCK_SINGS:
return True
'''
for ins in block_item.ins_list[:1]:
if ins.mnemonic in ['movz','movk','cmp','b.eq','b.ne']:
return True
'''
return False
def get_func_blocks(self, func_start, func_end):
'''
跟IDA一样,以跳转分割函数成片
:param func_start: 函数起始地址
:param func_end: 函数结束地址
:return:
'''
func_bin = self.so_bin[func_start:func_end]
ins_list = self.capstone.disasm(func_bin, func_start)
# 起始地址=> blockItem 的 map
block_map = {}
# 分发器
tmp_jump_map = {}
processors = []
# 死循环地址
dead_loop = []
ins: capstone.CsInsn = None
block_item: BlockItem = None
new_block = True
for ins in ins_list:
ins_str = '0x%x: %s %s' % (ins.address, ins.mnemonic, ins.op_str)
# 如果是新的代码块,初始化一个blockItem
if new_block:
block_item = BlockItem()
block_item.start_addr = ins.address
block_item.ins_list = []
new_block = False
block_item.ins_list.append(ins)
# 设置是否包含bl指令
if self._is_bl(ins):
block_item.has_bl_ins = True
if self._is_ret(ins):
block_item.has_ret_ins = True
if self._is_csel(ins):
block_item.has_csel_ins = True
# 判断是否为跳转指令或ret指令
if self._is_block_end(ins) and not self._is_bl(ins):
# logger.debug(','.join([str(x) for x in ins.groups]) + "###" + ins_str)
jump_addr = self._get_ins_imm(ins)
block_item.end_addr = ins.address
block_item.jump_addr = jump_addr
# 向临时的分发器添加跳转地址
tmp_jump_map[jump_addr] = tmp_jump_map.get(jump_addr, 0) + 1
# 判断是否是死循环
if jump_addr == ins.address:
dead_loop.append(jump_addr)
block_map[block_item.start_addr] = block_item
new_block = True
# 去除循环的地址
for addr in dead_loop:
del tmp_jump_map[addr]
# 如果某个代码块的引用大于1,就可能是分发器
for addr, num in tmp_jump_map.items():
if num > 1:
processors.append(addr)
return block_map, processors
def get_real_blocks(self, block_map: dict, processor: list):
'''
获取真实代码块
:param block_map:
:param processor:
:return:
'''
real_blocks = set()
for start_addr, block_item in block_map.items():
# 如果某个代码块含有BL指令那一定是真实块
if block_item.has_bl_ins:
real_blocks.add(start_addr)
# 引用分发器的代码块就可能为真实块
elif block_item.jump_addr in processor:
real_blocks.add(start_addr)
elif block_item.has_ret_ins:
real_blocks.add(start_addr)
# 根据特征删除虚假块
real_blocks = filter(lambda addr: not self._is_fake_block(block_map[addr]), real_blocks)
return [addr for addr in real_blocks]
def find_next_block(self, func_context: FuncContext, start_addr, branch_control=1):
func_context.branch_control = branch_control
func_context.trace_list = []
func_context.is_success = False
func_context.dist_addr = None
func_context.start_addr = start_addr
try:
self.mu.emu_start(func_context.start_addr, 0x10000)
except unicorn.UcError as e:
pc = self.mu.reg_read(unicorn.arm64_const.UC_ARM64_REG_PC)
if pc != 0:
return self.find_next_block(func_context, pc+4, branch_control)
else:
logger.error("find_next_block, pc: 0x%x, err: %s" % (pc, e))
return func_context.dist_addr
def get_real_block_flows(self, func_context: FuncContext):
# 生成mu
self.mu = self._get_mu(func_context)
# 将函数起始地址从真实块中去除
if func_context.func_start_addr in func_context.real_blocks:
func_context.real_blocks.remove(func_context.func_start_addr)
# 起始流地址
queue = [(func_context.func_start_addr, None)]
flows = {}
while len(queue) != 0:
pc, reg_vals = queue.pop()
self._set_mu_context(reg_vals)
# 已经处理过的就跳过
if pc in flows:
continue
flows[pc] = []
ctx = self._get_mu_context()
pc1 = self.find_next_block(func_context, pc, 0)
if pc1 is not None:
queue.append((pc1, self._get_mu_context()))
flows[pc].append(pc1)
block_item: BlockItem = func_context.block_map.get(pc)
if block_item.has_csel_ins:
self._set_mu_context(ctx)
pc2 = self.find_next_block(func_context, pc, 1)
if (pc2 is not None) and (pc1 != pc2):
queue.append((pc2, self._get_mu_context()))
flows[pc].append(pc2)
return flows
def _generate_patch(self, origin_addr, branchs, condition=None) -> bytes:
if condition is not None:
codes, _ = self.ks.asm("b%s #0x%x;b #0x%x" % (condition, branchs[0], branchs[1]), origin_addr, as_bytes=True)
else:
codes, _ = self.ks.asm(("b #0x%x" % branchs[0]), origin_addr, as_bytes=True)
return codes
def _generate_nop_patch(self, num) -> bytes:
codes, _ = self.ks.asm('nop', as_bytes=True)
return codes * num
def patch_func(self, func_context: FuncContext, flows):
patch_list = []
for start_addr, branchs in flows.items():
if len(branchs) == 0:
continue
block_item: BlockItem = func_context.block_map.get(start_addr)
patch_addr = None
shellcode = None
if len(branchs) == 2:
csel_ins = block_item.csel_ins
patch_addr = csel_ins.address
condition = csel_ins.op_str[-2:]
shellcode = self._generate_patch(patch_addr, branchs, condition=condition)
if len(branchs) == 1:
b_ins = block_item.last_ins
patch_addr = b_ins.address
shellcode = self._generate_patch(patch_addr, branchs)
if patch_addr is not None and shellcode is not None:
patch_list.append((patch_addr, shellcode))
for start_addr, block_item in func_context.block_map.items():
if start_addr not in flows:
block_size = block_item.end_addr - block_item.start_addr + 4
shellcode = self._generate_nop_patch(int(block_size / 4))
patch_list.append((start_addr, shellcode))
tmp_so_bin = bytearray(self.so_bin)
for patch_addr, shellcode in patch_list:
for ch in shellcode:
tmp_so_bin[patch_addr] = ch
patch_addr += 1
self.so_bin = bytes(tmp_so_bin)
def proccess_func(self, start_addr, end_addr):
block_map, processors = self.get_func_blocks(start_addr, end_addr)
real_blocks = self.get_real_blocks(block_map, processors)
func_context = FuncContext()
func_context.func_start_addr = start_addr
func_context.func_end_addr = end_addr
func_context.block_map = block_map
func_context.real_blocks = real_blocks
func_context.trace_list = []
flows = self.get_real_block_flows(func_context)
self.patch_func(func_context, flows)
def dump(self, save_path):
with open(save_path, 'wb') as fp:
fp.write(self.so_bin)
if __name__ == '__main__':
ollvm = FuckArm64Ollvm('libvdog.so')
ollvm.proccess_func(0x70438, 0x7170C)
ollvm.dump('libvdog_new.so') |
|
|
[原创]简单完善《ARM64 OLLVM反混淆》中的脚本
capstone regname转uncorn regid def UR(regname):
return getattr(unicorn.arm64_const, 'UC_ARM64_REG_{0}'.format(regname.upper()), None)
最后于 2022-2-25 14:13
被evilbeast编辑
,原因:
|
|
|
|
|
|
|
|
|
[原创]分享一个自己做的函数抽取壳
LoadMethod 可以直接使用结构体 // 1e0K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3q4G2M7%4m8^5M7X3g2X3i4K6u0W2j5$3!0E0i4K6u0r3j5h3&6V1M7X3!0A6k6q4)9J5k6o6p5I4i4K6u0W2x3q4)9J5k6e0m8Q4y4h3k6J5x3U0q4Q4x3V1k6^5M7X3g2X3i4K6u0r3j5i4u0@1i4K6u0r3L8r3W2T1k6r3g2^5k6X3W2D9k6g2)9J5c8X3c8W2P5q4)9J5c8X3c8W2P5q4)9#2k6X3k6A6L8r3g2Q4x3X3g2Z5i4K6t1K6z5o6p5@1
class DexFile {
public:
void* virutal_table_;
uint8_t* begin_;
size_t size_;
uint8_t* data_begin_;
size_t data_size_;
std::string location_;
uint32_t location_checksum_;
};
// 4e2K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3q4G2M7%4m8^5M7X3g2X3i4K6u0W2j5$3!0E0i4K6u0r3j5h3&6V1M7X3!0A6k6q4)9J5k6o6p5I4i4K6u0W2x3q4)9J5k6e0m8Q4y4h3k6J5x3U0q4Q4x3V1k6^5M7X3g2X3i4K6u0r3j5i4u0@1i4K6u0r3L8r3W2T1k6r3g2^5k6X3W2D9k6g2)9J5c8X3c8W2P5q4)9J5c8X3y4D9j5i4y4K6i4K6g2X3j5h3y4U0k6i4y4K6L8%4u0Q4x3X3g2Z5i4K6t1K6x3K6V1`.
class ClassAccessor {
public:
class BaseItem {
public:
const DexFile* dex_file_;
const uint8_t *ptr_pos_ = nullptr;
const uint8_t *hiddenapi_ptr_pos_ = nullptr;
uint32_t index_ = 0u;
uint32_t access_flags_ = 0u;
uint32_t hiddenapi_flags_ = 0u;
};
class Method : public BaseItem {
public:
bool is_static_or_direct_ = true;
uint32_t code_off_ = 0u;
};
};使用 // 6c3K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3q4G2M7%4m8^5M7X3g2X3i4K6u0W2j5$3!0E0i4K6u0r3j5h3&6V1M7X3!0A6k6q4)9J5k6o6p5I4i4K6u0W2x3q4)9J5k6e0m8Q4y4h3k6J5x3U0q4Q4x3V1k6^5M7X3g2X3i4K6u0r3j5i4u0@1i4K6u0r3M7Y4g2F1N6r3W2E0k6g2)9J5c8X3y4D9j5i4y4K6i4K6g2X3L8r3W2F1K9$3g2J5i4K6u0W2j5$3y4Q4x3@1k6J5i4K6y4p5i4K6t1$3j5h3#2H3i4K6y4n7L8h3!0Q4x3@1b7I4y4K6l9@1x3o6y4Q4x3U0k6S2L8i4m8Q4x3@1u0X3K9g2)9K6c8o6x3^5y4K6W2Q4x3U0x3K6z5o6M7&6
void LoadMethod_R(void* thiz, const DexFile* dex_file, ClassAccessor::Method& method, const void* klass, void* dest)
{
DLOGD("enter LoadMethod_R hook1");
g_originLoadMethod_R(thiz, dex_file, method, klass, dest);
std::string location = dex_file->location_;
int idx = dexNumber(&location);
uint8_t* begin = dex_file->begin_;
if (location.find("base.apk") == std::string::npos)
return;
if (method.code_off_ == 0) {
return;
}
uint8_t* codeAddr = dex_file->begin_ + method.code_off_ + 16;
uint16_t firstDvmCode = *((uint16_t*)(codeAddr));
if (firstDvmCode != 0x0012 && firstDvmCode != 0x0016 && firstDvmCode != 0x000e)
{
return;
}
// 改写保护
if (!MultiDexCode::getInstance()->hasProtect(idx))
{
changeDexProtect(begin, location.c_str(), dex_file->data_size_, idx);
}
std::string sCode;
uint32_t offsetOfDex = 0;
DLOGD("dexIdx: %d", idx-1);
if (!MultiDexCode::getInstance()->getCode(idx-1, method.index_, sCode, offsetOfDex))
{
return;
}
if (method.code_off_ != (offsetOfDex - 16)) {
return;
}
DLOGD("method_index: %d, code_off: %d, myCode_off: %d", method.index_, method.code_off_, offsetOfDex);
memcpy(codeAddr, sCode.c_str(), sCode.size());
} |
|
|
[原创]分享一个自己做的函数抽取壳
我看楼主加了android 11中 hook MapFileAtAddress的代码,我测试没有成功的原因 return "_ZN3art6MemMap16MapFileAtAddressEPhmiiilbPKcbPS0_PNSt3__112basic_stringIcNS5_11char_traitsIcEENS5_9allocatorIcEEE"; 2. Dobby hook框架有bug, 当hook的函数参数超过8个时,就会崩溃,调试了下发现堆栈不平,还不知道怎么修复dobby, 可以在MapFileAtAddress中找其他函数hook, 如MapInternal |
|
|
|
操作理由
RANk
{{ user_info.golds == '' ? 0 : user_info.golds }}
雪币
{{ experience }}
课程经验
{{ score }}
学习收益
{{study_duration_fmt}}
学习时长
基本信息
荣誉称号:
{{ honorary_title }}
勋章
兑换勋章
证书
证书查询 >
能力值