首页
社区
课程
招聘
[原创]flare_emu或idapython批量处理解密程序
发表于: 2020-11-2 17:32 4752

[原创]flare_emu或idapython批量处理解密程序

2020-11-2 17:32
4752

分析某样本遇到两个解密函数,第一个函数引用位置下图,被调用105次:
图片描述

函数传参有寄存器传参,push 字符串地址,还有先mov到寄存器再入栈,展示一处:
图片描述
10072EFE入栈就是待解密的字符串。

该解密算法比较简单,指针值减去下标+1 mod 10:
图片描述
直接写解密算法:

data是传入的待解密字符串。

然后是解决怎么找到调用此解密函数地址,直接xfreTo函数拿到:
图片描述

拿到调用函数位置就要往上找入参的待解密字符串,
图片描述

addr传入的是引用解密函数位置,PreHead是该地址向上寻找地址,GetMnem获得地址的指令,GetOpnd获得指令的参数,GetOperandValue获得指令参数数据,详见idc文档,简单的一批,设置i指定寻找四次就返回。
该段代码意思就是找调用解密算法函数位置上面的入栈解密数据:
图片描述
测试一下,跟上面图比较看:
图片描述

拿到字符串地址之后就是读取字符串,一直向后读取到null,也可以直接getString,但是不准:

所以整个过程是,循环找调用解密函数位置,找到之后寻找解密字符串,找到取出来,再调用解密函数,最后添加注释,完整如下:

看一下解密之后效果:
图片描述
图片描述
图片描述

如果是寄存器入栈idc有点鸡肋,简单用一下模拟执行,寄存器入栈:
图片描述
配置flare_emu官方有不赘述,顺便说一下官网demo的取值是直接物理取值,而栈空间在虚拟执行的时候返回之后都平衡了,直接取idb里面的数据基本拿不到:
图片描述
不在意,我们主要是用它来帮忙解决寄存器入栈的数据。

注册eh实例,第一个参数idc返回解密函数地址,第二个自定义回调函数:
图片描述

然后它可以帮忙找到寄存器的值:
图片描述
图片描述

address是调用函数位置,后面就是解密函数的三个参数,所以能拿到需要的数据位置,可以配合idc完成后面的操作:
图片描述
鸡肋代码:

其实大可以直接模拟执行完成了,但是处理虚拟内存一直报错,(这就是强行用6.8环境跑flare_emu的问题吧)

这样就可以全解密了:
图片描述

第二个解密函数只是算法上的不同,逆向算法的时候比较鸡贼,需要动态调试配合,代码加了膨胀只能参考,不能依赖:
图片描述
第一个函数初始化一个256位的数组,然后第二个下标开始,先取出数组值,数组值再计算出一个位置,把那个位置的数组值取出来,两个交换,交换完成之后再两数相加赋值给第二个位置的数组,虽然很绕,直接动调dump完事:

第二个函数是真解密函数,数组经过上面同样的操作之后,再把两个位置的数据相加再计算一个偏移,这个偏移取出再和加密数据异或完成解密:

之后都可以按照上面的解密步骤相似运行。

 
 
def decrypt(data):
    length=len(data)
    i =0
    out=''
    while i<length:
        out += chr(ord(data[i])-(i+1)%10)
        i+=1
    return out
def decrypt(data):
    length=len(data)
    i =0
    out=''
    while i<length:
        out += chr(ord(data[i])-(i+1)%10)
        i+=1
    return out
 
 
 
 
def get_string(addr): 
  out = ""
  while True:
    if Byte(addr) != 0:
      out += chr(Byte(addr))
    else:
      break
    addr += 1
  return out
def get_string(addr): 
  out = ""
  while True:
    if Byte(addr) != 0:
      out += chr(Byte(addr))
    else:
      break
    addr += 1
  return out
from binascii import *
def decrypt(data):
    length=len(data)
    i =0
    out=''
    while i<length:
        out += chr(ord(data[i])-(i+1)%10)
        i+=1
    return out
 
'''suanfa  1
def find_function_arg(addr):
    i=0
    while True:
        i+=1
        addr=PrevHead(addr)
        print(hex(addr)+GetMnem(addr))     
        if (GetMnem(addr)=="push") and  ("eax" not in GetOpnd(addr,0)) and ("esi" not in GetOpnd(addr,0)) and ("edi" not in GetOpnd(addr,0)) and ("ebx" not in GetOpnd(addr,0)):
            print("angr addr:0x%x" % GetOperandValue(addr, 0))
            return GetOperandValue(addr, 0)
            break
        if i>5:
            return 0
    return 0
'''
def find_function_arg(addr):
    i=0
    while True:
        i+=1
        addr=PrevHead(addr)
        print(hex(addr)+GetMnem(addr))     
        if (GetMnem(addr)=="mov" and "edi" in GetOpnd(addr,0)):
            print("angr addr:0x%x" % GetOperandValue(addr, 1))
            return GetOperandValue(addr, 1)
            break
        if i>3:
            return 0
    return 0
 
 
 
def get_string(addr): 
  out = ""
  while True:
    if Byte(addr) != 0:
      out += chr(Byte(addr))
    else:
      break
    addr += 1
  return out
'''
xef=find_function_arg(0x1003310E)
data = get_string(xef)
dec = decrypt(data)
print "function addr: 0x%x | Decrypted: %s" % (0x1003310E, dec)
MakeComm(0x1003310E, dec)
MakeComm(xef, dec)
'''
 
 
for addr in XrefsTo(0x10031B76, 0):
    xef=find_function_arg(addr.frm)
    if xef!=0:
        data = get_string(xef)
        dec = decrypt(data)
        print "function addr: 0x%x | Decrypted: %s" % (addr.frm, dec)
        MakeComm(addr.frm, dec)
        MakeComm(xef, dec)
from binascii import *
def decrypt(data):
    length=len(data)
    i =0
    out=''
    while i<length:
        out += chr(ord(data[i])-(i+1)%10)
        i+=1
    return out
 
'''suanfa  1
def find_function_arg(addr):
    i=0
    while True:
        i+=1
        addr=PrevHead(addr)
        print(hex(addr)+GetMnem(addr))     
        if (GetMnem(addr)=="push") and  ("eax" not in GetOpnd(addr,0)) and ("esi" not in GetOpnd(addr,0)) and ("edi" not in GetOpnd(addr,0)) and ("ebx" not in GetOpnd(addr,0)):
            print("angr addr:0x%x" % GetOperandValue(addr, 0))
            return GetOperandValue(addr, 0)
            break
        if i>5:
            return 0
    return 0
'''
def find_function_arg(addr):
    i=0
    while True:
        i+=1
        addr=PrevHead(addr)
        print(hex(addr)+GetMnem(addr))     
        if (GetMnem(addr)=="mov" and "edi" in GetOpnd(addr,0)):
            print("angr addr:0x%x" % GetOperandValue(addr, 1))
            return GetOperandValue(addr, 1)
            break
        if i>3:
            return 0
    return 0
 
 
 
def get_string(addr): 
  out = ""
  while True:
    if Byte(addr) != 0:
      out += chr(Byte(addr))
    else:
      break

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

最后于 2021-1-30 17:00 被kanxue编辑 ,原因:
收藏
免费 1
支持
分享
最新回复 (2)
雪    币: 83
活跃值: (1087)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
2
666
2020-11-3 04:41
0
雪    币: 26398
活跃值: (63257)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
3
感谢分享~
2021-1-12 18:30
0
游客
登录 | 注册 方可回帖
返回
//