情感测试
情感测试

您现在的位置: 情感测试简介_情感测试玩法 > 情感测试物语 > 使用unicorn对ollvm字符串进行

使用unicorn对ollvm字符串进行

发布时间:2021-8-26 12:03:14   点击数:
本文为看雪论坛优秀文章看雪论坛作者ID:新萌

题目出自3w班1月第一题——对抗字符串混淆。

样本是一个比较初级的ollvm混淆,其字符串解密过程在init_array中,所以so文件正常加载到内存中后,其加密的字符串就已经解密后写回原始地址了。所以我们可以通过unicorn加载so文件,手动将解密后的字符串写回so文件,经过简单的patch就可以静态分析了。本文参考了leadroyal与smartdone大佬的文章。使用unicorn对字符串进行解密。问题一:偷懒使用unicorn直接将整个so文件load进memory,读取data的数据全是00,修复后也是错误的,我按照leadroyal大佬的脚本修改后是正确的。问题二:有时候使用unicornmap后,代码看着没有问题,但是跑起来就报错,可能你需要看看你分配的内存是不是不是的倍数。脚本如下:

importbinasciiimportmathimportida_bytesimportidaapifromcapstoneimport*fromelftools.elf.elffileimportELFFilefromelftools.elf.sectionsimportSymbolTableSectionfromkeystoneimport*fromunicornimport*fromunicorn.arm_constimport*classFILFINIT(object):def__init__(self,file,mode):self.file=fileself.fd=self.file_init(mode)self.elf=ELFFile(self.fd)self.file_size=self.file_size()self.data_divs=self.get_data_div()deffile_init(self,mode=rb+):fd=open(self.file,mode=mode)returnfddeffile_close(self):self.fd.close()deffile_seek_to(self,seekto):self.fd.seek(seekto,0)deffile_read(self,size=-1):binary=self.fd.read(size)returnbinarydeffile_write(self,data):self.fd.write(data)deffile_size(self):importosreturnos.path.getsize(self.file)defget_data_div(self):data_divs=[]ifself.elf:symtab=self.elf.get_section_by_name(.dynsym)assertisinstance(symtab,SymbolTableSection)forsyminsymtab.iter_symbols():#sym.name:strifsym.name.startswith(.datadiv):data_divs.append(sym.entry.st_value)returndata_divsclassUCINIT(object):def__init__(self,file,mode,offset=0x,stack_size=0x,data_size=0x):self.cs=Cs(CS_ARCH_ARM,CS_MODE_THUMB)self.fileinfo=FILFINIT(file,mode)self.data_divs=self.uc_filter()self.func_start_and_end=self.get_func_start_and_end()self.uc=unicorn.Uc(UC_ARCH_ARM,UC_MODE_THUMB)self.image_base=0xself.offset=offsetself.stack_size=stack_sizeself.data_size=data_sizeself.image_size=(math.ceil(self.fileinfo.file_size/self.offset)+1)*self.offsetself.uc.mem_map(self.image_base,self.image_size)self.init_seg()#self.uc.mem_write(self.image_base,self.fileinfo.file_read())#全文件导入是错误的,不知道为什么self.stack_base=self.image_base+self.image_size+self.offsetself.stack_top=self.stack_base+self.stack_size-0xself.uc.mem_map(self.stack_base,self.stack_size)self.uc.reg_write(UC_ARM_REG_SP,self.stack_top)self.data_base=self.stack_base+self.stack_size+self.offsetself.uc.mem_map(self.data_base,self.data_size)definit_seg(self):segs=[segforseginself.fileinfo.elf.iter_segments()ifseg.header.p_type==PT_LOAD]forseginsegs:self.uc.mem_write(self.image_base+seg.header.p_vaddr,seg.data())definit_reg(self,regs):index=0forreginregs:reg_num=66+indexself.uc.reg_write(reg_num,reg)defuc_run(self,target,end):targ=target+self.image_baseutil=self.image_base+endself.uc.emu_start(targ,util)defuc_stop(self):self.uc.emu_stop()self.fileinfo.file_close()defregister_hook_code(self,htype,callback):self.uc.hook_add(htype,callback)defuc_filter(self,size=0x):data_divs=[]fordata_divinself.fileinfo.data_divs:self.fileinfo.file_seek_to(data_div-1)data=self.fileinfo.file_read(size)forinisinself.cs.disasm(data,0):ifinis.mnemonic==bxandinis.op_str==lr:continueelse:data_divs.append(data_div)self.fileinfo.file_seek_to(0)returndata_divsdefget_func_start_and_end(self):data_divs=[]fordata_divinself.data_divs:func=idaapi.get_func(data_div)func_start_and_end=(data_div,func.end_ea-0x)data_divs.append(func_start_and_end)returndata_divsdefget_elf_data(self):data_section_header=self.fileinfo.elf.get_section_by_name(.data).headerprint([+].dataaddr{}-{}.format(hex(data_section_header.sh_addr),hex(data_section_header.sh_size)))new_data=self.uc.mem_read(self.image_base+data_section_header.sh_addr,data_section_header.sh_size)print([+].databinary{}.format(binascii.hexlify(new_data)))returnnew_datadefpatch_so_data(self):data_section_header=self.fileinfo.elf.get_section_by_name(.data).headerdata_addr=data_section_header.sh_addr#self.fileinfo.file_seek_to(data_addr)#self.fileinfo.file_write(self.get_elf_data())new_data=self.get_elf_data()#new_data:bytearrayprint([+]patchsodataaddr{}\n{}.format(hex(data_addr),bytes(new_data)))ida_bytes.patch_bytes(data_addr,bytes(new_data))defpatch_data_div(self):ks=Ks(KS_ARCH_ARM,KS_MODE_THUMB)fordata_divinself.data_divs:binary=ks.asm(bxlr)print(bytes(binary[0]))#print(struct.pack(B,binary[0]))print([+]patchsotext.datadiv{}\n{}.format(hex(data_div-1),bytes(binary[0])))ida_bytes.patch_bytes(data_div-1,bytes(binary[0]))defhook_code(uc:unicorn.Uc,address,size,user_data):cs=Cs(CS_ARCH_ARM,CS_MODE_THUMB)me=uc.mem_read(address,size)forcodeincs.disasm(me,size):print("[+]Tracinginstructionsat0x%x,instructionssize=ix%x,inst:%s%s"%(address,size,code.mnemonic,code.op_str))defhook_mem_access(uc,access,address,size,value,user_data):ifaccess==UC_MEM_WRITE:print([+]MemoryisbeingWRITEat0x%x,datasize=%u,datavalue=0x%x%(address,size,value))else:#READme=uc.mem_read(address,size)print([+]MemoryisbeingREADat0x%x,datasize=%u,datavalue=0x%s%(address,size,binascii.hexlify(me)))if__name__==__main__:print([+]Sofileparsestarting!)so=UCINIT(libcrack.so,rb)#so.get_elf_data()forstart,endinso.func_start_and_end:print([+]Datadivaddr{}-{}.format(hex(start),hex(end)))so.init_reg((0,0,0))#so.register_hook_code(UC_HOOK_CODE,hook_code)#so.register_hook_code(UC_HOOK_MEM_READ,hook_mem_access)#so.register_hook_code(UC_HOOK_MEM_WRITE,hook_mem_access)so.uc_run(start,end)so.patch_data_div()#so.patch_so_data()#so.get_elf_data()so.uc_stop()print([+]Sofilerunfinished!)uemu对字符串进行解密"class="anchor"href="#使用uemu对字符串进行解密"使用uEmu对字符串进行解密。

#下载uEmu$gitclone

转载请注明:http://www.zmax-alibaba.com/qgwy/138066.html

网站简介 | 发布优势 | 服务条款 | 隐私保护 | 广告合作 | 合作伙伴 | 版权申明 | 网站地图

当前时间: