wmsuper 发表于 2017-8-20 14:50

关于某游戏的混淆符号解析

0x01 前言
函数符号对于逆向分析来说是十分重要,如果符号被混淆将会加大分析的难度,这次遇到的是一个cocos2dx的游戏,关键的函数名被混淆。


0x02 分析
本来不打算解密混淆的函数名,但是在分析过程中发现一个解密关键字符串的函数。


它用的是循环异或来解密加密后的字符串,会不会混淆的函数名也使用了这种加密方式?可能性非常大。

但是用这个函数的秘钥去解密函数名解出来的是乱码,秘钥可能是不同的,那么如何获取密码呢?网上的方式是基于文本字符统计的方式去猜所使用的循环异或秘钥,
但是有没有比较好的方法呢?

0x03 猜秘钥
在浏览函数名我发现一个比较有意思的类,它有一个Encode的函数,那会不会有一个Decode函数呢?
看下图那个框起来的函数,刚好6字节,参数也对得上,或许就是我们要找的函数,因为是循环异或,所以可以通过明文和密文直接算出秘钥
秘钥:0702050003,通过该秘钥去解密其他字符串,都能解密成功,所以猜测是正确的。{:1_912:}


0x04 批量重命名
可以方便的通过idaPython去重命名类似“_ZN26BAGA516B7669616B675765607312BAGA6B676374Ev”的c++修饰的函数名。
主要思路是获取所有导出函数名,再通过相应的解析规则去替换函数名称,代码如下:
import idaapi
import idautils
import idc
import binascii
import string
#解密字符串
def dec_name(str):
      str
      key=binascii.a2b_hex('0702050003')
      keylen=len(key)
      str=binascii.a2b_hex(str)
      strlen=len(str)
      de_str=''
      for i in range(0,strlen):
                de_str+=chr((ord(key)^ord(str))&0xff)
      return de_str
#获取长度前缀
def getint(str):
      pos=0
      for i in range(0,len(str)):
                if(str.isdigit()):
                        pos=i+1
                else:
                        if pos>0:
                              return pos
      return 0
#获取改名后的符号
def getsysm(str):
      rep_str=[]
      if(str=='_ZN'):
                i=3
                while i<len(str):
                        pos=getint(str)
                        if pos<=0:
                              break;
                        pre_len=str
                        int_len=string.atoi(pre_len)
                        ba_str=str
                        if(ba_str=='BAGA'):
                              dec_str=dec_name(ba_str)
                        else:
                              i+=int_len+len(pre_len)
                              continue
                        
                        rep_str+=[]
                        i+=int_len+len(pre_len)
                for i in rep_str:
                        str=str.replace(i,i)   #替换相应的字符串
                return str
                        
      else:
                return None
funlist=list(idautils.Entries())   #获取导出函数
for i in funlist:
      str=getsysm(i)
      if str:
                idc.MakeNameEx(i,str,idc.SN_NOWARN)

跑完脚本后,基本上重命名完成了,发送和接受,加密和解密的地方都可以看出来,一般不用分析加解密函数,直接call发包函数就能发包,因为用于连接服务器的对象的this指针一般是不变的(单例模式),
如何获取上述指针能?简单的打个hook就能获取了。


0x05 结束
如果碰上那种符号被混淆的很厉害或者根本没符号的那应该怎么办?发送函数最终还是调用send(tcp ),可以从send入手,一直往上,但是很可能跟不到发送的地方。
因为一般封装的用于处理发送和接受的消息的类,都不是直接发的,而是插入一个队列或者类似队列的地方,由update函数进行发送,这种异步的发送方式可以从队列下手
就能发现sendMsg的函数了。

caddy 发表于 2017-8-20 15:15

脚本很赞。

煦涵 发表于 2017-8-20 15:19

楼主厉害666

tomemouse 发表于 2017-8-20 16:37

脚本很赞哦{:301_971:}

mayl8822 发表于 2017-8-20 16:57

感谢分享

可坏 发表于 2017-8-20 17:27

脚本超级赞{:301_999:}

xiaofengzi 发表于 2017-8-20 18:36

其实混淆的研究还是会较多的,记得以前在看雪上看到12种以上的混淆情况

艾莉希雅 发表于 2017-8-20 19:28

混淆强于加壳233333

wentwent 发表于 2017-8-20 20:50

围观 学习

l145191039l 发表于 2017-8-21 21:41

这是啥游戏. 小白白哦是俺不懂
页: [1] 2
查看完整版本: 关于某游戏的混淆符号解析