Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Unicorn实战(二):去掉armariris的字符串加密
from elftools.elf.constants import P_FLAGS
from elftools.elf.elffile import ELFFile
from elftools.elf.sections import SymbolTableSection
from unicorn import Uc, UC_ARCH_ARM, UC_MODE_LITTLE_ENDIAN, UC_PROT_WRITE, UC_PROT_READ, UC_PROT_EXEC
from unicorn.arm_const import *
from capstone import Cs, CS_ARCH_ARM, CS_MODE_THUMB, CsInsn
from keystone import Ks, KS_MODE_THUMB, KS_ARCH_ARM, KS_MODE_ARM
import struct
filename = "./libcms.so"
fd = open(filename, 'r+b')
elf = ELFFile(fd)
# 遍历符号表,找到.datadiv_decode开头的函数
datadivs = []
dynsym = elf.get_section_by_name(".dynsym")
assert isinstance(dynsym, SymbolTableSection)
for symbol in dynsym.iter_symbols():
if symbol.name.startswith('.datadiv_decode'):
datadivs.append(symbol.entry.st_value)
# 加载 so 到内存中
def align(addr, size, align):
fr_addr = addr // align * align
to_addr = (addr + size + align - 1) // align * align
return fr_addr, to_addr - fr_addr
def pflags2prot(p_flags):
ret = 0
if p_flags & P_FLAGS.PF_R != 0:
ret |= UC_PROT_READ
if p_flags & P_FLAGS.PF_W != 0:
ret |= UC_PROT_WRITE
if p_flags & P_FLAGS.PF_X != 0:
ret |= UC_PROT_EXEC
return ret
load_base = 0
emu = Uc(UC_ARCH_ARM, UC_MODE_LITTLE_ENDIAN)
load_segments = [x for x in elf.iter_segments() if x.header.p_type == 'PT_LOAD']
for segment in load_segments:
fr_addr, size = align(load_base + segment.header.p_vaddr, segment.header.p_memsz, segment.header.p_align)
emu.mem_map(fr_addr, size, pflags2prot(segment.header.p_flags))
emu.mem_write(load_base + segment.header.p_vaddr, segment.data())
STACK_ADDR = 0x7F000000
STACK_SIZE = 1024 * 1024
start_addr = None
emu.mem_map(STACK_ADDR, STACK_SIZE, UC_PROT_READ | UC_PROT_WRITE)
emu.reg_write(UC_ARM_REG_SP, STACK_ADDR + STACK_SIZE)
# 调用datadiv
for datadiv in datadivs:
print("Function invoke", hex(datadiv))
emu.reg_write(UC_ARM_REG_LR, 0)
emu.emu_start(datadiv, 0)
print("Function return")
# Patch data
print("Patch data")
data_section_header = elf.get_section_by_name('.data').header
new_data = emu.mem_read(data_section_header.sh_addr, data_section_header.sh_size)
fd.seek(data_section_header.sh_offset)
fd.write(new_data)
# Patch datadiv 直接返回
print("Patch datadiv")
ks_thumb = Ks(KS_ARCH_ARM, KS_MODE_THUMB)
ks_arm = Ks(KS_ARCH_ARM, KS_MODE_ARM)
for datadiv in datadivs:
fd.seek(datadiv & 0xFFFFFFFE)
if datadiv & 0x1 == 0x1:
a = ks_thumb.asm('bx lr')[0]
else:
a = ks_arm.asm('bx lr')[0]
for _ in a:
fd.write(struct.pack("B", _))
fd.close()
print("done!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment