非华为电脑安装华为电脑管家分析

VSole2022-01-17 16:19:05

近期有使用手机投屏的需求,用过几个小工具感觉效果不是很理想,所以想着着手分析下。

1分析环境

软件版本 :11.1.6.31 (PCManager_Setup_11.1.6.31(C233D005).exe)

虚拟机 :windows 10 21H2 x64

真机 :windows 10 21H1 x64

工具 :IDA 、VS 2019

测试手机 :华为 Mate 30 5G

2首次安装运行分析

从华为电脑管家官网(https://consumer.huawei.com/cn/support/pc-manager/)上下载最新版本的安装包后,给我的感觉是一个类似与msi的安装包。

将安装包拖入虚拟机,同时打开process monitor抓取一波安装时的行为,方便后续分析。

首先最直观的提示是:

同样是windows,华为电脑和其友商电脑有什么区别?我感觉最直观的体现在于下图:

有这个方向下一步就需要关注下针对主板或者系统信息的一次操作。

3分析安装包

将安装包拖入到ida中,在入口函数处竟然发现了一个明显的提示:

这华为电脑管家安装包应该是通过NSIS(https://nsis.sourceforge.io/Main_Page)打包生成的。之前使用过NSIS进行过打包,该工具主要通过编写一个脚本文件(*.nsi/*.ini等)完成一系列操作。例子如下:

用7Z直接解压PCManager_Setup_11.1.6.31(C233D005).exe看看是否可能从修改脚本重打包的方式绕过对设备的检测。

但是在压缩包的根目录并没有找到相关的脚本文件,因此这个方法并不可行。

不过既然解压了就试下解压后的可执行文件是否能运行。在解压目录找到PCManager.exe运行。

 

可以直接运行,难道就此结束吗?跟着窗口的各种提示一路点击"同意",但是还是有问题。

 

可能是跳过了安装过程没有给安装上服务的原因,点击"修复"。

 连接手机并进入"多屏协同"。此时并不能正常识别到手机。

 到此看来,似乎并不能通过解压的方式正常运行"华为电脑管家"。

4

分析安装流程中的模块

知道了安装包并不包含主要的逻辑代码,那么就需要从安装包中包含的模块入手分析。

回到开始时用process monitor抓取到的信息中,在日志中可以看到一条信息。

 

通过命令行参数可以大胆猜测下,这里可能就是验证设备兼容性的函数。在IDA中定位到MBAInstallPre.exe中对参数isSupportDevice判断的位置。

通过观察流程该函数Func_isSupportDevice主要有两个可能的返回值,分别是 : 1 或 2

首先进入函数sub_1400162D0

该函数在入口处调用了一次导入函数之后便进入到字符串的拼接环节。

这里主要看下导入函数的工作流程。

 

 

这里多次跟进ProductAdapt::MachineType::GetInstance后发现会进入到一个函数__int64 __fastcall ProductAdapt::MachineType::LoadConfig(ProductAdapt::MachineType *this)

在函数ProductAdapt::MachineType::LoadConfig再次发现了Func_isSupportDevice里用到的一个类实例SmBiosHelper::GetInstance()

看来这个SmBiosHelper这个类才是真正干活的。该函数由HardwareHal.dll导出。

在其初始化函数中发现了如下调用:

下面是函数sub_180032750的主要逻辑:

通过MSDN GetSystemFirmwareTable发现该函数可以读取到SMBIOS固件表。同时该函数也提到了使用WMI也可以获取到。

通过GitHub代码 DumpSMBIOS尝试获取数据。

通过wbemtest.exe打开ROOT\WMI并打开类MSSMBios_RawSMBiosTables找到SMBiosData

显示SMBiosData字段无数据。

这里不清楚为什么通过WMI GUI工具没有获取到数据,已经管理员方式运行了。

通过上图可以看出来使用GetSystemFirmwareTable确实可以拿到主板信息。由上图中可以知道,如果通过GetSystemFirmwareTable可以拿到信息之后则跳过了通过WMI方式获取数据。

在拿到SMBiosData字段或者说SMBIOSTableData字段后,程序进行了如下处理。

主要对其中的5个字段进行了解析(文章结尾提供BIOS更多信息)。分别是:

BIOS Information (Type 0)System Information  (Type 1)Baseboard (or Module) Information  (Type 2)System Enclosure  (Type 3)OEM Strings (Type 11)

回到函数sub_1400162D0内部,当函数ProductCheckSupport::GetDeviceTypeEx返回后,则会得到对应设备的GetProductName,通过返回的ProductName与软件Config中包含的ProductName进行比较。

 

如果与Config中的ProductName一致,则函数返回1否则返回0

至此函数sub_1400162D0流程分析完毕。下面来看Func_isSupportDevice中的else分支。

else分支直接通过SmBiosHelper::GetSysManufactor来获取主板制造商。并将字符串转换为大写后与HUAWEI和XXXX进行比较。

 

如果主板厂商是HUAWEI则函数返回1,否则函数返回2。

至此MBAInstallPre.exe中的Func_isSupportDevice函数分析完毕。

5模块分析总结

通过上面的对其中的MBAInstallPre.exe->isSupportDevice流程的大概分析可以知道,模块HardwareHal.dll中的类SmBiosHelper会通过函数GetSystemFirmwareTable或者WMI来获取主板信息。

接下来则通过hook函数GetSystemFirmwareTable处理其返回值。

通过MSDN GetSystemFirmwareTable知道正确的函数调用方式如下:

DWORD error = ERROR_SUCCESS;DWORD smBiosDataSize = 0;RawSMBIOSData* smBiosData = NULL; // Defined in this linkDWORD bytesWritten = 0;
// Query size of SMBIOS data.// 第一次调用时为了获取SMBIOSData的数据大小smBiosDataSize = GetSystemFirmwareTable('RSMB', 0, NULL, 0);
// Allocate memory for SMBIOS datasmBiosData = (RawSMBIOSData*) HeapAlloc(GetProcessHeap(), 0, smBiosDataSize);if (!smBiosData) {    error = ERROR_OUTOFMEMORY;    goto exit;}
// Retrieve the SMBIOS table// 第二次调用时为了获取SMBIOSData的数据
bytesWritten = GetSystemFirmwareTable('RSMB', 0, smBiosData, smBiosDataSize);
if (bytesWritten != smBiosDataSize) {    error = ERROR_INVALID_DATA;    goto exit;}
// Process the SMBIOS data and free the memory under an exit label

主要代码如下(修改自GitHub代码 DumpSMBIOS)。

更多BIOS结构信息在文章结尾提供相关链接。

UINT WINAPI Hooked_GetSystemFirmwareTable( _In_ DWORD FirmwareTableProviderSignature, _In_ DWORD FirmwareTableID, _Out_writes_bytes_to_opt_(BufferSize, return) PVOID pFirmwareTableBuffer, _In_ DWORD BufferSize){    PTF_LOG_A("Hooked_GetSystemFirmwareTable.");    UINT uRetValue = 0;
    uRetValue = g_FUNC_GetSystemFirmwareTable(FirmwareTableProviderSignature, FirmwareTableID, pFirmwareTableBuffer, BufferSize);
    if (FirmwareTableProviderSignature != 'RSMB')    {        PTF_LOG_A("Hooked_GetSystemFirmwareTable. Signature is not \'RSMB\'");        return uRetValue;    }
    if (pFirmwareTableBuffer != NULL && BufferSize > 0 && uRetValue <= BufferSize)    {        PTF_LOG_A("Hooked_GetSystemFirmwareTable. Modify Data.");        const PRawSMBIOSData pDMIData = (PRawSMBIOSData)pFirmwareTableBuffer;        //修改返回数据        DumpSMBIOSStruct(pDMIData, pDMIData->Length);        PTF_LOG_A("Hooked_GetSystemFirmwareTable. Modify Data Finish.");    }    return uRetValue;}
void DumpSMBIOSStruct(void* pAddress, unsigned int Len){    LPBYTE p = (LPBYTE)(pAddress);    const LPBYTE lastAddress = p + Len;    PSMBIOSHEADER pHeader;
    for (;;) {        pHeader = (PSMBIOSHEADER)p;
        if (ModiySysInfo(pHeader) == true)            break;
        if ((pHeader->Type == 127) && (pHeader->Length == 4))            break; // last avaiable tables        LPBYTE nt = p + pHeader->Length; // point to struct end        while (0 != (*nt | *(nt + 1))) nt++; // skip string area        nt += 2;        if (nt >= lastAddress)            break;        p = nt;    }}
/*ModiySysInfo 函数 为了防止格式识别错误,最好是删除当前System Information节。自己重新构建一个节并添加到全部数据的尾部。同时需要更新GetSystemFirmwareTable返回值的大小。以上前提是提供给GetSystemFirmwareTable的输出缓冲区足够长。*/bool ModiySysInfo(PSMBIOSHEADER pHeader){    if (pHeader->Type == 1)    {        /*https://consumer.huawei.com/cn/support/laptops/matebook-e/*/        PSystemInfo pSystem = (PSystemInfo)pHeader;        char* str = (char *)pHeader + pHeader->Length;        const char* pszManufacturer = "HUAWEI";//主板厂商        const char* pszProductName = "BLl-W19";//产品名        const char* pszVersion = "1.0";//版本        //https://consumer.huawei.com/cn/support/warranty-query/        //这里的SerialNumber在测试中发现了个小问题        //如果未提供一个可用的SN则不能在软件中使用某些联网功能        //如 "玩机技巧" "快捷服务" 等        const char* pszSerialNumber = "ASM51ASMASM51ASM";//16位主板序列号
        //获取原各字段信息        const char* pszOldManufacturer = LocateStringA(str, pSystem->Manufacturer);        const char* pszOldProductName = LocateStringA(str, pSystem->ProductName);        const char* pszOldVersion = LocateStringA(str, pSystem->Version);        const char* pszOldSerialNumber = LocateStringA(str, pSystem->SN);
        if (            strlen(pszOldManufacturer) > strlen(pszManufacturer) &&            strlen(pszOldProductName) > strlen(pszProductName)&&            strlen(pszOldVersion) > strlen(pszVersion)&&            strlen(pszOldSerialNumber) > strlen(pszSerialNumber)            )        {            //如果原主板信息足够长则可以直接修改            PTF_LOG_A("Data length enough.");            str = ModiyStringData(str, pszManufacturer);            str = ModiyStringData(str, pszProductName);            str = ModiyStringData(str, pszVersion);            str = ModiyStringData(str, pszSerialNumber);            return true;        }        else        {            //原主板信息较短,则需要另辟蹊径            //...        }    }    return false;}
char * ModiyStringData(char* pAddress, const char* pszTargetData){    if (0 == *pAddress)        return pAddress;    int nTragetLen = strlen(pszTargetData) + 1;    strcpy_s(pAddress, nTragetLen, pszTargetData);    return (pAddress + nTragetLen);}

6最终效果

str函数char函数
本作品采用《CC 协议》,转载必须注明作者和本文链接
这里根据红日安全PHP-Audit-Labs对一些函数缺陷的分析,从PHP内核层面来分析一些函数的可利用的地方,标题所说的函数缺陷并不一定是函数本身的缺陷,也可能是函数在使用过程中存在某些问题,造成了漏洞,以下是对部分函数的分析
如何调包Win32API函数?其实就是HookPE文件自己的IAT表。
Glibc2.29及以上版本堆的利用技巧越来越复杂,简直就是神仙打架,实在学得有点头晕。并且很多时候就算我们有了复用堆块在出题人的各种围追堵截的限制下,也可能没办法getshell,所以一直在不断开发新的利用姿势。
前言本文主要着眼于glibc下的一些漏洞及利用技巧和IO调用链,由浅入深,分为 “基础堆利用漏洞及基本IO攻击” 与 “高版本glibc下的利用” 两部分来进行讲解,前者主要包括了一些glibc相关的基础知识,以及低版本glibc下常见的漏洞利用方式,后者主要涉及到一些较新的glibc下的IO调用链。
VMPWN的入门系列-1
2023-07-27 09:45:00
今天的文章有点长,图片比较多,请耐心阅读5.1 实验一 VMPWN15.1.1 题目简介这是一道基础的VM相关题目,VMPWN的入门级别题目。
在当前CTF比赛中,“伪造IO_FILE”是pwn题里一种常见的利用方式,并且有时难度还不小。
前言最近一段时间在研究Android加壳和脱壳技术,其中涉及到了一些hook技术,于是将自己学习的一些hook技术进行了一下梳理,以便后面回顾和大家学习。主要是进行文本替换、宏展开、删除注释这类简单工作。所以动态链接是将链接过程推迟到了运行时才进行。
之后想到了更完美的办法
漏洞的成因来自于Glibc在对重定向函数进行延迟绑定时,由于参数表被篡改导致的控制流篡改,本篇中,笔者会尽可能通过例题和实际现象来阐释 延迟绑定的底层实现 和 ret2dlresolve。
在我们学习c语言的时候我们就知道在输出或者输入的时候需要使用%s%d等等格式化字符,此处不过多介绍,详情可以去看看c语言的基础知识。
VSole
网络安全专家