作者论坛账号:SNSD99
0.前言
最近好奇这个充电保护程序为什么可以控制最高充电百分比,所以我想分析一下。
该程序适用于华硕飞行堡垒fx63vd7700型号,如果适用华硕其它型号的可以试试看。
注意该充电保护程序不适用于其它品牌、或华硕其它型号的笔记本电脑。
这个软件的界面如下图所示。
模式有三种:完整充电模式、平衡保养模式、最佳保养模式。三种模式限制充电百分比分别为100%,80%、和60%。
目录如下:
1.x64dbg动态调试
双击BhcApp.exe,启动充电保护软件。x64dbg附加“BhcMgr.exe”。
在DeviceIoControl处插入断点,这个函数用于和设备通信,随便选中一个模式然后点确定就会触发断点。
例如我选中的“平衡保养模式”。
调用堆栈如下图所示。
DeviceIoControl的参数如下:
BOOL
DeviceIoControl
(
[
in
] HANDLE hDevice,
[
in
] DWORD dwIoControlCode,
[
in
, optional] LPVOID lpInBuffer,
[
in
] DWORD nInBufferSize,
[
out
, optional] LPVOID lpOutBuffer,
[
in
] DWORD nOutBufferSize,
[
out
, optional] LPDWORD lpBytesReturned,
[
in
,
out
, optional] LPOVERLAPPED lpOverlapped
)
;
回到DeviceIoControl上层函数“sub_321C90”。观察DeviceIoControl的入参:
HANDLE hDevice = 0x274
DWORD dwIoControlCode = 0x22240C
LPVOID lpInBuffer = 0xB7F010
DWORD nInBufferSize = 0x10
LPVOID lpOutBuffer = 0x93F238
DWORD nOutBufferSize = 0x400
LPDWORD lpBytesReturned = 0x93F234
LPOVERLAPPED lpOverlapped = 0
1.1 查看缓冲区lpInBuffer: 0xB7F010
如下图所示为缓冲区内容,大小0x10字节。
这个可以视为一个结构体。代码如下。
struct
BatteryIOCtlInfo
{
DWORD head;
// 头部
DWORD nextSize;
// 后续结构体成员大小
DWORD num2;
// 未知四字节数,固定为0x120057
DWORD perecent;
// 充电百分比,0x50为80%,0x3C为60,0x64为100%
};
结构体各成员值填写为:
BatteryIOCtlInfo btinfo;
btinfo.head =
0x53564544
;
btinfo.nextSize=
8
;
btinfo.num2 =
0x120057
;
// 0x3c 60%
// 0x50 80%
// 0x64 100%
btinfo.perecent =
0x3c
;
1.2 输出缓冲区lpOutBuffer: 0x93F238
只有头四节被填充0x1,剩余的0x400 - 4个字节均为0.
输出缓冲区里的内容没有什么特别的,只需保证有输出缓冲区,以及该缓冲区有0x400字节大小即可。
2.IDA静态分析
以上分析了DeviceIoControl的入参,但是还不知道设备句柄是怎么获取的。
进入sub_321C90的代码段,在IDA为“sub_401C90”,00401D0C为调用DeviceIoControl的语句。
选中"hDevice",按下X键看看哪个语句写入了这个hDevice。如下图所示。(Type:r表示读取read,w表示写入write)
进入了函数sub_401D70。
原来是CreateFileW打开(电池)设备的句柄。
CreateFileW参数如下:
HANDLE
CreateFileW
(
[
in
]
LPCWSTR
lpFileName,
[
in
]
DWORD
dwDesiredAccess,
[
in
]
DWORD
dwShareMode,
[
in
,
optional
]
LPSECURITY_ATTRIBUTES
lpSecurityAttributes,
[
in
]
DWORD
dwCreationDisposition,
[
in
]
DWORD
dwFlagsAndAttributes,
[
in
,
optional
]
HANDLE
hTemplateFile
);
LPCWSTR lpFileName:"\.ATKACPI"
DWORD dwDesiredAccess: 0xC0000000 ( GENERIC_READ | GENERIC_WRITE == 0xC0000000 )
DWORD dwShareMode: 0x3 (FILE_SHARE_READ | FILE_SHARE_WRITE == 0x3)
LPSECURITY_ATTRIBUTES lpSecurityAttributes: NULL
DWORD dwCreationDisposition: 0x3 (OPEN_EXISTING == 3)
DWORD dwFlagsAndAttributes: NULL
HANDLE hTemplateFile: NULL
3. 代码复现
因此控制笔记本最高充电百分比的C++代码如下:
struct
BatteryIOCtlInfo
{
DWORD head;
DWORD nextSize;
DWORD num2;
DWORD perecent;
};
int
main
(
int
argc,
char
** argv,
char
** envp)
{
// GENERIC_READ | GENERIC_WRITE == 0xC0000000
// FILE_SHARE_READ | FILE_SHARE_WRITE == 0x3
// OPEN_EXISTING == 3
HANDLE hhh = CreateFileW
(
L"\\.\ATKACPI"
,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL
,
OPEN_EXISTING,
NULL
,
NULL
);
//
BatteryIOCtlInfo btinfo;
btinfo.head =
0x53564544
;
btinfo.nextSize=
8
;
btinfo.num2 =
0x120057
;
// 0x3c 60%
// 0x50 80%
// 0x64 100%
btinfo.perecent =
0x3c
;
// 修改此处数值
// out buffer
void
* out_buf =
malloc
(
0x400
);
DWORD returnBytes =
0
;
//
DeviceIoControl(
hhh,
0x22240C
,
&btinfo,
sizeof
(btinfo),
out_buf,
0x400
,
&returnBytes,
NULL
);
CloseHandle(hhh);
free
(out_buf);
return
0
;
}
经测试可以修改最高充电百分比,但是只能有60%,80%和100%三种数值。如果修改为其它数值,则默认最高充电百分比为100%。
-官方论坛
www.52pojie.cn
原文始发于微信公众号(白帽子):华硕fx63vd7700充电保护程序“ASUS Battery Health Charging”逆向分析
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论